Как использование списка инициализаторов элементов предотвращает создание избыточного объекта в С++?

У меня есть вопрос о разнице в инициализации объекта со списком инициализаторов членов конструктора и без него.

В следующем фрагменте кода есть два класса Test1 и Test2, каждый с двумя конструкторами, объекты этих двух классов создаются в конструкторе по умолчанию другого класса Example. Объект Test1 создается с одним параметром в списке инициализаторов членов, тогда как объект Test2 создается с одним параметром внутри тела конструктора Example.

class Test1 {
public:
    Test1()      { cout << "Test1 is created with no argument"; }
    Test1(int a) { cout << "Test1 is created with 1 argument"; }
};

class Test2 {
public:
    Test2()      { cout << "Test2 is created with no argument"; }
    Test2(int a) { cout << "Test2 is created with 1 argument"; }
};

class Example {
public:
    Test1 objTest1;
    Test2 objTest2;

    Example() : objTest1(Test1(50)) 
    {
            objTest2 = Test2(50);
    }
};

int main() 
{
    Example e;
}

Вывод приведенного выше кода:

Test1 is created with 1 argument

Test2 is created with no argument

Test2 is created with 1 argument

Мои вопросы

  • Почему объект Test2 создается дважды? (Тот, который создан без инициализатора члена.)
  • Что случилось с лишним объектом Test2? Он все еще занимает часть памяти?
  • Как работает список инициализаторов членов при инициализации переменных-членов класса?
  • Есть ли какое-либо преимущество в производительности при использовании списка инициализаторов членов? (Поскольку Test1 создается только один раз)

person geekY    schedule 25.12.2018    source источник
comment
Test2 сначала создается без аргумента (конструктор по умолчанию), а затем во второй раз, когда вы вызываете его конструктор внутри тела конструктора Example. Что непонятного в этом поведении?   -  person πάντα ῥεῖ    schedule 25.12.2018
comment
Когда вы создаете пример e, он создает objTest2, а затем вы перезаписываете его новым объектом, в то время как вы указываете, как инициализировать objTest2 в конструкторе.   -  person Ian4264    schedule 25.12.2018


Ответы (1)


Ваш конструктор Example (неявно) эквивалентен

Example() : objTest1(Test1(50)), objTest2()
{
        objTest2 = Test2(50);
}

То есть объект objTest2 конструируется и инициализируется один раз неявно (это вставляется компилятором).

Затем внутри тела вы явно создаете и инициализируете временный объект Test2, который используется для назначения объекту objTest2.


Также обратите внимание, что в списке инициализаторов objTest1(Test1(50)) создает временный объект Test1 и передает его копирующему конструктору для инициализации objTest1 (хотя большинству компиляторов следует опускать это копирование) . Вы можете упростить его как обычный objTest1(50).

person Some programmer dude    schedule 25.12.2018