Согласно этому интервью с Will Kahan , они были основаны на форматах VAX F и G эпохи.
Конечно, что doesn «Ответ на вопрос о том, как эти форматы были выбраны ...
В чем разница между
blockquote>Object obj(args...)
иObject obj{args...}
?Первая - direct-initialization , а вторая - direct -list-инициализации . Это упоминается в двух разных разделах:
§8.5 / 16 [dcl.init]
Инициализация, которая происходит в формах
T x(a); T x{a};
, а также в выражениях
blockquote>new
(5.3.4),static_cast
(5.2.9), преобразования типа функциональных обозначений (5.2.3) и инициализаторы базиса и члена (12.6. 2) называется прямой инициализацией .и §8.5.4 / 1 [dcl.init.list]
List-initialization - инициализация объекта или ссылки из braced-init-list . Такой инициализатор называется списком инициализаторов , а разделяемые запятой -инициализаторы-предложения списка называются элементами списка инициализаторов. Список инициализаторов может быть пустым. Инициализация списка может возникать в контекстах с прямой инициализацией или копированием; list-initialization в контексте прямой инициализации называется direct-list-initialization , а инициализация списка в контексте инициализации копирования называется copy-list-initial-initialization .
blockquote>
Есть несколько отличий между ними:
- Если построенный тип имеет конструктор, который принимает аргумент
initializer_list
, direct-list-initialization всегда будет поддерживать этот конструктор. Другие конструкторы будут рассмотрены только в том случае, если конструкторinitializer_list
не является жизнеспособным. §13.3.1.7 / 1 [over.match.list]- direct-list-initialization не позволяет сужать преобразования в списке аргументов. §8.5.4 / 3 [dcl.init.list]
- Если инициализированный тип является агрегатом, direct-list-initialization будет выполнять агрегатная инициализация. §8.5.4 / 3 [dcl.init.list]
- Порядок оценки элементов braced-init-list из слева направо. §8.5.4 / 4 [dcl.init.list]
- Вы можете избежать наиболее неприятного анализа с помощью direct-list-initialization
& nbsp;
struct foo{}; struct bar { bar(foo const&) {} }; bar b1(foo()); // most vexing parse bar b2(foo{}); // all 3 of the following construct objects of type bar bar b3{foo()}; bar b4{foo{}};
В чем разница между Object obj (args ...) и Object obj {args ...}?
blockquote>{args ...} будет предпочтительнее конструктор с список initializer_list по другим законным кандидатам.
std::vector<int> v(10); // vector of size 10 std::vector<int> v{10}; // vector initialized with a single element, (int) 10
С другой стороны, вы отказываетесь от неявного сужения.
std::vector<int> v(10.5); // vector of size 10 std::vector<int> v{10.5}; // illegal - no compile std::vector<float> v{10.5}; // vector initialized with a single element, (float) 10.5
В чем разница между Object obj (args ...) и Object obj {args ...}? и почему Скотт говорит так.
blockquote>. Разница в том, что в первом случае порядок оценки аргументов не имеет значения (т. е. неуказан), но в последнем случае порядок остается слева (например, в котором они появляются).
Следующий текст из 5.2.2 / 8 [expr.call] (n3690) относится к форме
Object(args...)
:Оценки постфиксного выражения и аргументов не имеют никакого значения относительно друг друга. Все побочные эффекты оценок аргументов секвенированы до ввода функции (см. 1.9).
blockquote>И текст из $ 8.5.4 / 4 [dcl.init.list] (n3690) имеет дело с
Object{args...}
form:В списке инициализаторов списка с привязкой-инициализацией предложения инициализатора, включая все, которые являются результатом разложений пакетов (14.5.3), оцениваются в порядок, в котором они появляются. То есть вычисление каждого значения и побочный эффект, связанный с заданным предложением инициализатора, секвенируются перед вычислением каждого значения и побочным эффектом, связанным с любым предложением инициализатора, которое следует за ним в списке списка инициализаторов, разделенных запятыми. [Примечание: это порядок оценки выполняется независимо от семантики инициализации; например, он применяется, когда элементы списка инициализатора интерпретируются как аргументы вызова конструктора, хотя обычно нет ограничений последовательности для аргументов вызова. - end note]
blockquote>Ну, это означает:
int f() { static int i = 10; return ++i; } //increment the static int! Object obj(f(), f()); //is it obj(11,12) or obj(12,11)? Unspecified. Object obj{f(), f()}; //it is obj(11,12). Guaranteed.
Обратите внимание, что GCC (4.7.0 и 4.7.2) имеют ошибку из-за форма
{}
не работает так, как должна . Я не уверен, исправлена ли она в текущей версии.Надеюсь, что это поможет.
Поведение Object obj(args...)
и Object{args...}
зависит от конструкторов, определенных в Object
.
Возьмем следующий пример:
#include <iostream>
#include <initializer_list>
struct A
{
A(int a, int b) {std::cout << "Came to A::A()\n";}
};
struct B
{
B(int a, int b) {std::cout << "Came to B::B(int, int)\n";}
B(std::initializer_list<int> in) {std::cout << "Came to B::B(std::initializer_list<int>)\n";}
};
int main()
{
A a1(10, 20); // Resolves to A(int, int)
A a2{10, 20}; // Resolves to A(int, int)
A a3{30}; // Does not resolve to anything. It's a compiler error.
B b1(10, 20); // Resolves to B(int, int)
B b2{10, 20}; // Resolves to B(std::initializer_list<int> )
B b3{30}; // Resolves to B(std::initializer_list<int> )
}