Почему вызывает конструктор копирования при передаче временного значения по ссылке 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
Ответы
Ответ 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) явным, и вы не должны сталкиваться с этой ошибкой.
Изменить: Я думаю, что неправильно понял вопрос. Я мог бы удалить это.