Синтаксис конструктора C ++ - PullRequest
       14

Синтаксис конструктора C ++

12 голосов
/ 25 февраля 2009

Простой вопрос: эквивалентны ли следующие утверждения? или второй делает больше скрытых вещей за кулисами (если так, что?)

myClass x(3);
myClass x = myClass(3);

Спасибо! * * 1004

Ответы [ 4 ]

25 голосов
/ 25 февраля 2009

Они не полностью идентичны. Первый называется «прямой инициализацией», а второй - «инициализацией копирования».

Теперь Стандарт составляет два правила. Первый предназначен для прямой инициализации и для инициализации копии, где инициализатор имеет тип инициализированного объекта. Второе правило - для инициализации копии в других случаях.

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

Второй называется copy-initialization, потому что, если тип инициализатора другого типа, создается временный объект при попытке неявного преобразования правой стороны в левую:

myclass c = 3;

Компилятор создает временный объект типа myclass тогда, когда есть конструктор, который принимает int. Затем он инициализирует объект с этим временным. Также в этом случае созданный временный объект может быть создан непосредственно в инициализированном объекте. Вы можете выполнить эти шаги, печатая сообщения в конструкторах / деструкторах вашего класса и используя опцию -fno-elide-constructors для GCC. Он не пытается удалить копии тогда.

Кстати, этот код не имеет ничего общего с оператором присваивания. В обоих случаях происходит инициализация.

8 голосов
/ 25 февраля 2009

Второй может вызывать или не требовать дополнительной myclass конструкции объекта, если копирование не выполнено вашим компилятором. Однако в большинстве конструкторов разрешение копирования включено по умолчанию даже без какого-либо переключателя оптимизации.

Примечание инициализация, когда конструкция никогда не вызывает оператора присваивания.

Всегда помните:

назначение: уже существующий объект получает новое значение

инициализация: новый объект получает значение в момент его рождения.

5 голосов
/ 25 февраля 2009

Во втором случае сначала создается временный объект, а затем копируется в объект x с помощью конструктора копирования myClass. Следовательно, оба не одинаковы.

4 голосов
/ 25 февраля 2009

Я написал следующее, чтобы попытаться проиллюстрировать понять, что происходит:

#include <iostream>

using namespace std;

class myClass
{
public:
    myClass(int x)
    {
        this -> x = x;
        cout << "int constructor called with value x = " << x << endl;
    }

    myClass(const myClass& mc)
    {
        cout << "copy constructor called with value = " << mc.x << endl;
        x = mc.x;
    }

    myClass & operator = (const myClass & that)
    {
        cout << "assignment called" << endl;
        if(this != &that)
        {
            x = that.x;
        }
        return *this;
    }

private:
    int x;
};

int main()
{
    myClass x(3);
    myClass y = myClass(3);
}

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

$ ./a.out
int constructor called with value x = 3
int constructor called with value x = 3

Это может показаться , чтобы показать, что нет разницы между двумя вызовами, выполненными в основной функции, но это было бы неправильно. Как указывало litb , конструктор копирования должен быть доступным для работы этого кода, даже если в этом случае он исключается. Чтобы доказать это, просто переместите конструктор копирования в приведенном выше коде в закрытый раздел определения класса. Вы должны увидеть следующую ошибку:

$ g++ myClass.cpp 
myClass.cpp: In function ‘int main()’:
myClass.cpp:27: error: ‘myClass::myClass(const myClass&)’ is private
myClass.cpp:37: error: within this context

Также обратите внимание, что оператор присваивания никогда не вызывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...