почему конструктор копирования вызывается при передаче временного по константной ссылке? - PullRequest
23 голосов
/ 19 января 2011

Я передаю неназванный временный объект функции, определенной с помощью параметра const ref. Копия ctor класса является частной, и я получаю ошибку компиляции. Я не понимаю, почему конструктор копирования вызывается в этой ситуации.

class A {
public:
  A(int i) {}
private:
  A(const A&) {}
};

void f(const A& a)
{
}

int main()
{
  f(A(1)); // <-- error here: 'A::A(const A&)' is private
}

Как и ожидалось, когда я меняю основной на:

A a(1);
f(a);

это работает.

РЕДАКТИРОВАТЬ: компилятор GCC 4.1.2

Ответы [ 3 ]

20 голосов
/ 19 января 2011

Выражение A(1) является значением r * 5.2.3 [expr.type.conv].

При инициализации ссылки const (аргумент функции) с выражением, котороеэто rvalue , компилятор может создать временное и скопировать значение этого выражения во временное и связать эту ссылку с этим временным.8.5.3 [dcl.init.ref] / 5.

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

Обратите внимание, что это поведение связано с изменением в следующей версии C ++.В новом стандарте ссылка const, инициализированная из класса prvalue , должна быть привязана непосредственно к объекту ссылки;В этом случае нельзя создавать временные объекты, а конструктор копирования не используется или не требуется.

18 голосов
/ 19 января 2011

Вы можете найти ответ на свой вопрос в Копировать конструктор, необходимый с временным объектом или перейти непосредственно к http://gcc.gnu.org/bugs/#cxx%5Frvalbind

Стандарт C ++ говорит, что временный объект должен быть создан в этом контекст и его содержание заполнены копия объекта, который мы пытаемся привязать к ссылке; это также говорит что временная копия может быть удалена, но семантические ограничения (например, доступность) конструктора копии еще нужно проверить.

Для получения дополнительной информации вы можете обратитесь к следующим пунктам стандарт C ++: [dcl.init.ref] / 5, пункт 2, подпункт 1 и [Class.temporary] /2.

Начиная с GCC 4.3.0, GCC больше не выдает ошибку для этого случая. это изменение основано на намерении C ++ языковой комитет. По состоянию на 2010-05-28, окончательный предложенный проект стандарта C ++ 0x позволяет это код без ошибок.

0 голосов
/ 19 января 2011

Поскольку a (1) вызывает конструктор A (int i), а затем A (const A &) вызывается при вызове void f (const A &).

Создайте конструктор A (int i)Ясно, и вы не должны сталкиваться с этой ошибкой.

Редактировать: Я думаю, что я неправильно понял вопрос.Я мог бы удалить это.

...