Правила доступа конструктора - PullRequest
3 голосов
/ 19 мая 2009

если я скомпилирую (под G ++) и запусту следующий код, он напечатает «Foo :: Foo (int)». Однако после того, как конструктор копирования и операторы присваивания стали частными, он не может быть скомпилирован со следующей ошибкой: «error: oo Foo :: Foo (const Foo &)’ private ») Почему ему нужен конструктор копирования, если он вызывает только стандартный конструктор во время выполнения?

#include <iostream>

using namespace std;

struct Foo {
    Foo(int x) {
        cout << __PRETTY_FUNCTION__ << endl;
    }


    Foo(const Foo& f) {
        cout << __PRETTY_FUNCTION__ << endl;
    }

    Foo& operator=(const Foo& f) {
        cout << __PRETTY_FUNCTION__ << endl;
        return *this;
    }
};

int main() {
    Foo f = Foo(3);
}

Ответы [ 2 ]

15 голосов
/ 19 мая 2009

Здесь используется конструктор копирования:

Foo f = Foo(3);

Это эквивалентно:

Foo f( Foo(3) );

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

Foo f(3);

Обратите внимание, что компилятор может решить оптимизировать вызов конструктора копирования, но конструктор копирования все еще должен быть доступен (т.е. не закрытым). Стандарт C ++ специально разрешает эту оптимизацию (см. Раздел 12.8 / 15), независимо от того, что на самом деле делает реализация конструктора копирования.

2 голосов
/ 19 мая 2009

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

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

Foo f = Foo(3);

требуется конструктор копирования. И

Foo f(3);

нет. Хотя это, вероятно, приведет к тому же двоичному коду.

Цитата из 12.8.15

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

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

- при временном уроке объект, который не был связан с ссылка (12.2) будет скопирована в объект класса с тем же CV-неквалифицированный тип, копия операция может быть опущена строительство временного объекта прямо в цель опущенная копия

См. Также «Оптимизация возвращаемого значения».

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