инициализация списка в сочетании с конструкторами

У меня есть структура с простым макетом, похожим на:

struct A
{
int a,b;
};

Я использовал равномерную инициализацию повсеместно для создания моей структуры, например:

A obj{2,3};

Позже я добавил конструктор в A. Теперь он выглядит так:

struct A
{
int a,b;
A(){}
};

Это нарушает использование равномерной инициализации. Есть ли простой способ сделать эту работу снова. Может быть, с помощью ключевого слова по умолчанию?

Я надеялся на что-то простое, чтобы соответствовать моей простой структуре.

1

Решение

Ваша исходная структура без конструкторов была агрегатного типа и поэтому позволяла вам использовать агрегатную инициализацию. Типы с предоставленными пользователем конструкторами не являются агрегатами, поэтому добавление конструктора нарушило использование инициализации агрегатов. Фактически, объявление этого конструктора делает его единственным конструктором и не позволяет инициализировать экземпляры этого типа любым другим способом, кроме как с этим конструктором.

Чтобы иметь такой конструктор, а также иметь возможность инициализировать экземпляры этого типа другими способами, вы должны объявить другие конструкторы с желаемым поведением. Если вы хотите иметь возможность инициализировать a и b, вы можете сделать что-то вроде следующего:

struct A
{
int a,b;
A(){}
A(int a_, int b_) : a(a_), b(b_) {}
};

Обратите внимание, что я ничего не упомянул о равномерной инициализации. Ничто из вышеперечисленного никоим образом не зависит от Uniform Initialization или C ++ 11. В чем заключается универсальная инициализация — это конкретный синтаксис, доступный для инициализации объектов.

В C ++ 03 агрегатная инициализация выглядела только так:

S s = {1, 2};

А в C ++ 03 использование конструктора выглядело так:

S s(1, 2);

В Uniform Initialization появилась возможность использовать один и тот же синтаксис для разных типов инициализации. То есть Единая инициализация может использоваться для агрегатной инициализации и инициализации через конструкторы.

Таким образом, в C ++ 11 вы можете использовать синтаксис:

A a{1, 2};

и это может быть агрегатная инициализация, если тип является агрегатом, или он может вызывать конструктор, если у типа есть конструкторы. Поскольку вы использовали Uniform Initialization для инициализации агрегата, чтобы продолжить использовать этот синтаксис с неагрегированным типом, вам просто нужно определить соответствующий конструктор.

2

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

Ваш простой конструктор вообще ничего не делает (даже не инициализирует a а также b). Если вы хотели их инициализировать, почему бы не сделать что-то вроде

struct A {
int a = 0, b = 0;
};

Сюда,

A x;
A y { 0 };
A z { 0, 0 };

Все работают и инициализируются a а также b до 0.

Если это не будет работать для вас, например, потому что у вас есть более сложный конструктор, тогда вы можете использовать делегирующие конструкторы следующим образом:

struct A {
int a, b;

A() : A(0, 0) { }
A(int x) : A(x, 0) { }
A(int x, int y) : a(x), b(y) { }
};

Или проще

struct A {
int a, b;

A(int x = 0, int y = 0) : a(x), b(y) { }
};

Все это будет работать с равномерной инициализацией.

5

В этом случае вы также должны объявить конструктор с двумя параметрами. Например

A( int a, int b ) : a( a ), b( b ) {}

Или вы можете объявить ваш конструктор по умолчанию как

A() = default;

без необходимости определять конструктор с двумя параметрами.

2

Если вы в C ++ 11, вы можете использовать std::initializer_list, Вот основной пример:

struct A{
int a, b;
A(initializer_list<int> ilist){
if (ilist.size() == 2){
a = *ilist.begin();
b = *ilist.begin() + 1;
}else //throw an exception
}
};

Теперь ваша структура может быть инициализирована как A var = {1, 2}

0

На самом деле вы должны избегать типа {a, b} для агрегатов в первую очередь:

struct A
{
int a,b;
A() : a(0), b(0) {};
A(std::initializer_list<int> list) : a(*list.begin()), b(*(list.begin()+1)) {};
A(int x, int y) : a(0), b(0) { /* no arguments for a and b */ }
};

int main() {
int array[] = { 1, 2 };
A x{{1, 2}};
A y = {1, 2};
A z(1, 2);
}
0
По вопросам рекламы [email protected]