Подтвердить что ты не робот

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

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

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
}

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

A a(1);
f(a);

он работает.

EDIT: компилятор gcc 4.1.2

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Выражение A(1) представляет собой rvalue 5.2.3 [expr.type.conv].

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

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

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

Ответ 3

Так как (1) вызывает конструктор A (int i), а затем A (const A &) вызывается в вызове void f (const A &).

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

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