2012-04-30 4 views
-1

Я прочитал, что ссылка возвращается из перегруженного оператора присваивания, чтобы включить цепочку операторов. Но без этого возвращения также работает цепочка операторов.Почему ссылка возвращается при перегрузке оператора присваивания?

Может кто-то пролить свет на это?

class A 
{ 
    public: 
     int x,y; 
     char* str; 

     //Default Constructor 
     A(){} 

     //Constructor 
     A(int a, int b, char* s){ 
      cout<<"initialising\n"; 
      x = a; 
      y = b; 
      str = new char[10]; 
      str = s; 
     } 

     //Destructor 
     ~A(){} 

     //Overloaded assignment operator 
     const A& operator=(const A& obj) 
     { 
      cout<<"Invoking Assignment Operator\n"; 
      x = obj.x; 
      y = obj.y; 
      str = new char[10]; 
      str = obj.str; 

      //return *this; 
     } 
}; 

ostream& operator<<(ostream& os, const A& obj) 
{ 
    os <<"X="<< obj.x<<" Y="<<obj.y<<" Str="<<obj.str<<"\n"; 
    return os; 
} 

int main() 
{ 
    A c(3,4,"Object C"); 
    cout<<c; 

    A d, e, f; 
    d = e = f = c; //Assignment operator invoked 3 times 
    cout<<e; 
} 

Выход:

initialising 
X=3 Y=4 Str=Object C 
Invoking Assignment Operator 
Invoking Assignment Operator 
Invoking Assignment Operator 
X=3 Y=4 Str=Object C 
+3

Ваш код даже не компилируется, как он может работать? –

+0

Вы возвращаетесь по ссылке, знаете ли вы об этом? –

+0

@ Luchian-Его компиляция и работа отлично для меня – cppcoder

ответ

2

Вы работаете в неопределенное поведение потому что возвращаемый тип ожидать от operator = является const A& и вы ничего не возвращаются.

Это просто не повезло, что он работает на вас. (да, неудачно, потому что не определено поведение, которое, как представляется, хуже)

Я получаю ошибку компиляции в MSVS, а ideone.com запускается во время выполнения.

http://ideone.com/xTDb6

+0

Странно, что он не компилируется на MSVS. Не имея оператора return в функции, объявленной как возвращающая non-'void', является законным (синтаксически и семантически допустимым). Это только время выполнения потока выполнения, достигающее закрывающей '}' функции, вызывающей UB. –

+0

@CharlesBailey IMO, MS получил это прямо на этом :) –

+0

Если 'new char [10]' throws есть законный путь выполнения, который позволяет избежать UB. IMHO MSVS ошибочно не компилирует это. –

2

Это правило возникло из кода что-то вроде этого:

struct Foo { 
    Foo& copy(const Foo& x) { 
     return (*this = x); 
    } 
}; 

В то время, две вещи были разные о C++:

  1. компилятор сгенерированный оператор = возвращается rvalue по умолчанию, и
  2. Компилятор разрешил привязку к нескольким константам для привязки к временному.

Код выше был предназначен, чтобы быть эквивалентно:

*this = x; 
return *this; 

Но это не было - так operator= возвратил RValue, компилятор генерируется временный для хранения результата выполнения задания, то, поскольку функция вернула ссылку, она вернула ссылку на эту временную. Тогда, конечно, дела пошли очень спешно, потому что у вас теперь была болтливая ссылка на временное, которое было уничтожено в конце полного выражения, в котором оно было создано. Короче говоря, случай класса, возвращающий ссылку на локальный, за исключением того, что потребовалось немало анализа, чтобы понять, что местный генерируется вообще, не говоря уже о ссылке на его возвращаемый.

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

 Смежные вопросы

  • Нет связанных вопросов^_^