Синтаксис списка инициализаторов в списке инициализаторов членов с использованием C ++ 11

Я прошел черезТур по С ++‘и Бьярне использует функцию списка инициализатора c ++ 11 при инициализации члена в конструкторе, например так (используя фигурные скобки):

A a;
B b;
Foo(Bar bar):
a{bar.a}, b{bar.b}
{}

Это, однако, не компилируется до c ++ 11. В чем разница со старым списком инициализирующих элементов (с использованием круглых скобок):

Foo(Bar bar):
a(bar.a), b(bar.b)
{}

Так в чем же разница и когда один должен быть предпочтительнее другого?

3

Решение

Так в чем же разница?

Круглые скобки работают только для типов, не относящихся к классам, или для типов с подходящим конструктором для количества аргументов в скобках.

Для них работают волнистые скобки, а также для агрегатов — просто struct или типы массивов без конструктора. Так что будет работать следующее:

struct {
int a,b;
} aggregate;
int array[2];

Foo() : aggregate{1,2}, array{3,4} {}

Наконец, фигурные скобки будут соответствовать конструктору, берущему подходящий тип initializer_list, а не конструктор с параметром (ами), чтобы соответствовать аргументам. Например:

std::vector<int> v1;
std::vector<int> v2;

Foo() :
v1(10,2),   // 10 elements with value 2
v2{10,2}    // 2 elements with value 10,2
{}

когда один должен быть предпочтительнее другого?

Предпочитайте круглые скобки, если вы хотите прояснить, что при инициализации используется конструктор, а не агрегат или initializer_list; или для принудительного использования определенного конструктора.

Предпочитайте фигурные скобки, когда вам нужна форма инициализации, которая не поддерживается иным образом; или когда вы просто хотите, чтобы инициализация «сделала правильные вещи».

В тех случаях, когда оба делают одно и то же, выбор в значительной степени эстетичен.

8

Другие решения

Там может быть разница в нескольких действительно раздражающие крайние случаи:

std::vector<int> v{3, 2}; // constructs a vector containing [3, 2]
std::vector<int> u(3, 2); // constructs a vector containing [2, 2, 2]

Это верно независимо от того, v а также u являются просто переменными в функции или являются членами класса, инициализированного в списке инициализации.

Но за исключением случаев, когда std::initializer_list<T> конструктор перекрывается с обычным конструктором, принимающим такое же количество аргументов, различий нет.

2

Краткое описание: обозначение в списке инициализатора члена совпадает с обозначением переменных, инициализированных в другом месте. К сожалению, описание того, что он делает, не так просто, потому что есть два несколько противоречивых изменения, связанных с использованием фигурных скобок для вызовов конструктора:

  1. унифицированный синтаксис инициализации было предназначена чтобы сделать, чтобы сделать, чтобы все конструкции использовали фигурные скобки, и он просто вызвал бы соответствующий конструктор, даже если это аргумент по умолчанию или у типа вообще нет конструктора и используется прямая инициализация.
  2. Для поддержки переменного числа аргументов можно использовать фигурные скобки, чтобы std::initializer_list<T> без дополнительной пары скобок / фигурных скобок. Если есть конструктор, принимающий std::initializer_list<T> (для подходящего типа T) этот конструктор используется при использовании фигурных скобок.

Поставить по другому, если есть нет std::initializer_list<T> конструктор, но какой-то другой определяемый пользователем конструктор использование скобок и фигурных скобок эквивалентно. В противном случае это вызывает std::initializer_list<T> конструктор. … и я предполагаю, что мне не хватает нескольких деталей, поскольку вся инициализация на самом деле довольно сложна.

0
По вопросам рекламы [email protected]