Почему конструктор копирования вызывается при передаче временного по константной ссылке?
Я передаю неназванный временный объект в функцию, определенную с параметром 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 ответа
Вы можете найти ответ на свой вопрос в конструкторе копирования, необходимом для временного объекта, или перейти непосредственно по http://gcc.gnu.org/bugs/.
Стандарт C++ говорит, что временный объект должен быть создан в этом контексте, и его содержимое должно быть заполнено копией объекта, который мы пытаемся связать со ссылкой; это также говорит, что временная копия может быть исключена, но семантические ограничения (например, доступность) конструктора копии все еще должны быть проверены.
Для получения дополнительной информации вы можете обратиться к следующим параграфам стандарта C++: [dcl.init.ref]/5, bullet 2, sub-bullet 1 и [class.tegoti]/2.
Начиная с GCC 4.3.0, GCC больше не выдает ошибку для этого случая. Это изменение основано на намерениях комитета по языку C++. Начиная с 2010-05-28, последний предложенный проект стандарта C++0x разрешает этот код без ошибок.
Выражение A(1)
является значением 5.2.3 [expr.type.conv].
При инициализации const
ссылка (аргумент функции) с выражением, являющимся значением, компилятор может создать временное и скопировать значение этого выражения во временное и связать эту ссылку с этим временным. 8.5.3 [dcl.init.ref] / 5.
[...] Конструктор, который будет использоваться для создания копии, должен вызываться независимо от того, выполняется ли копия на самом деле.
Обратите внимание, что это поведение связано с изменением в следующей версии C++. В новом стандарте const
ссылка, инициализированная из класса prvalue, должна быть привязана непосредственно к объекту ссылки; В этом случае нельзя создавать временные файлы, а конструктор копирования не используется или не требуется.
Поскольку a(1) вызывает конструктор A (int i), а затем A(const A&) вызывается при вызове void f(const A&).
Сделайте конструктор A (int i) явным, и вы не должны сталкиваться с этой ошибкой.
Изменить: я думаю, что я неправильно понял вопрос. Я мог бы удалить это.