Скопируйте конструктор, почему в функции возврата - PullRequest
4 голосов
/ 25 апреля 2010

Предположим, у меня есть:

class A
{
    A(A& foo){ ..... }
    A& operator=(const A& p) {  }
}

...
A lol;
...

A wow(...)
{

    return lol;
}

...
...
A stick;
stick = wow(...);

Тогда я получу ошибку компиляции в последней строке. Но если я добавлю «const» перед «A &», это нормально.

Я хочу знать почему. Где именно проблема? Я не понимаю, почему это должно быть постоянным.

Язык: C ++

Я отредактировал ... Я думаю, что изменение его уместно. Это дает ошибку.

Ответы [ 5 ]

1 голос
/ 25 апреля 2010

Я полагаю, что проблема, о которой вы говорите, похожа на:

c ++, время жизни объекта анонимных (неназванных) переменных

, где существенным моментом является то, что в C ++ анонимные временные данные не могут передаваться по ссылке, а только по константной ссылке.

1 голос
/ 25 апреля 2010

Следующий код прекрасно компилируется с Comeau и VC9:

class A
{
public:
    A() {}
    A(A&){}
};

A lol;

A wow()
{
    return lol;
}

int main()
{
    A stick;
    stick = wow();
    return 0;
}

Если это не компилируется с вашим компилятором, то я подозреваю, что ваш компилятор сломан. Если это так, то это означает, что вы должны были вставить настоящий код вместо предоставления фрагмента, который не похож на проблему, которую вы видите.

1 голос
/ 25 апреля 2010

Вызов wow приводит к временному объекту, r-значению. R-значения не могут быть назначены неконстантным ссылкам. Поскольку ваш конструктор копирования принимает неконстантные ссылки, вы не можете напрямую передать результат вызова wow. Вот почему добавление const решает проблему. Теперь конструктор копирования принимает константные ссылки, с которыми r-значения связываются просто отлично.

Скорее всего, ваш конструктор копирования не изменяет копируемый объект, поэтому параметр должен передаваться по const-reference. Именно так должны работать конструкторы копий, за исключением особых, задокументированных обстоятельств.

Но, как указывает sbi в своем ответе, этот конструктор копирования вообще не должен вызываться. Так что, хотя все это правда, это, скорее всего, не имеет ничего общего с вашей проблемой. Если нет ошибки компилятора. Возможно, ваш компилятор видит двухэтапную конструкцию и решил, что он отрежет посредника путем преобразования A stick; stick = wow(); в A stick = wow(); Но это будет ошибкой, о чем свидетельствует тот факт, что он выдает ошибку компиляции из совершенно юридический код Но без реального кода невозможно сказать, что на самом деле происходит. Должно быть несколько других ошибок, прежде чем возникнут проблемы с вашим конструктором копирования.

0 голосов
/ 25 апреля 2010

Эта функция:

A wow(...) 
{  ... }

возвращает объект по значению.
Это означает, что оно копируется обратно в точку, где была вызвана функция.

Эта строка:

stick = wow(...);  

Копирует конструкцию на флешку.
Значение, скопированное на карту памяти, является значением, скопированным обратно из функции wow ().
Но помните, что результатом вызова wow () является временный объект (он был скопирован обратно из wow (), но еще не находится в переменной).

Итак, теперь мы смотрим на конструктор копирования для A:

A(A& foo){ ..... }

Вы пытаетесь передать временный объект в ссылочный параметр. Это не разрешено Временный объект может быть связан только с константной ссылкой. Есть два решения проблемы:

1) Используйте константную ссылку.
2) Передать по значению в конструктор копирования.

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

0 голосов
/ 25 апреля 2010

Невозможно воспроизвести. Вам не хватает конструктора по умолчанию или вы забыли сделать конструкторы public?

См. http://www.ideone.com/nPsHj.

(Обратите внимание, что конструктор копирования может принимать аргумент cv A& с любой комбинацией const-volatile плюс некоторые аргументы по умолчанию. См. & Sect; [class.copy] / 2 в стандарте C ++.)


Редактировать: Интересно, что в g ++ - 4.3 (ideone) и 4.5 (с флагом -pedantic) нет ошибки компиляции, но в g ++ - 4.2 есть жалоба:

x.cpp: In function ‘int main()’:
x.cpp:19: error: no matching function for call to ‘A::A(A)’
x.cpp:7: note: candidates are: A::A(A&)
...