3

"opperator= should takes a parametor of the (of course,const best) ref of src obj",i see this in many books,but i try to use non-ref instead,it also works!so,whats the purpose of using ref?is it just to avoid copy from the param? my test code are,

#include <iostream>
#include <string>
using namespace std;

class Student{
public:
    Student& operator=(Student);
    string name;
    int num;
};

Student& Student::operator=(Student s)
{
    name=s.name;
    num=s.num;
    return *this;
}

int main(){
Student src;
src.name="haha";
src.num=11;
cout<<src.name<<" "<<src.num<<endl;
Student dst=src;
cout<<src.name<<" "<<src.num<<endl;
}
user2864740
  • 60,010
  • 15
  • 145
  • 220
aishuishou
  • 83
  • 7
  • possible duplicate of [Why should the copy constructor accept its parameter by reference in C++?](http://stackoverflow.com/questions/2685854/why-should-the-copy-constructor-accept-its-parameter-by-reference-in-c) – fredoverflow Mar 02 '14 at 07:21

5 Answers5

1

There are really two issues here:

1) The copy-assignment operator you've defined doesn't get called. The line

Student dst=src;

doesn't call the copy-assignment operator! It calls the copy constructor, which is defined implicitly by the compiler. However, if you wrote

Student dst;
dst = src;

then operator= would be called.

2) Yes, the purpose is to avoid copying. When you call a function, including operator=, which takes a Student by value, the Student object argument has to be copied (through an implicit call to the copy constructor). If the function takes a reference, on the other hand, then no copy is made.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
1

Because otherwise it would be passed by value, which is a copy, so you would need to invoke the copy constructor to invoke the copy constructor ...

user207421
  • 305,947
  • 44
  • 307
  • 483
0

This

Student& Student::operator=(Student s)
{
    name=s.name;
    num=s.num;
    return *this;
}

Should be

Student& Student::operator=(const Student &s)
{
    if (this == &s) return *this;
    name=s.name;
    num=s.num;
    return *this;
}

Use references to avoid wastage of CPU

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
0

In C++03, passing by const reference avoids making a potentially expensive new copy just for the local s, which is never modified, in addition to copying s into the destination object.

In C++11, now we have move semantics: Assignment may result in resource transfer to a new object, or resource copying. The pass-by-copy operation can be leveraged to produce the copied data which is used for the destination object, so the overhead is put to good use. If you pass using move, there is no copy. The best practice in C++11 is to let a single function serve as both the copy and move assignment operator:

Student& Student::operator=(Student s)
{
    name = std::move( s.name );
    num = s.num;
    return *this;
}
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • ... And it may be the same object – Ed Heal Mar 02 '14 at 03:52
  • 1
    @BrianBi: No, not if an r-value argument was passed. It only has to be moved in that case. – Benjamin Lindley Mar 02 '14 at 04:03
  • @BenjaminLindley point taken. Still, if an lvalue is passed then a copy will be made when calling the function, whereas if the parameter were a reference then that copy would be avoided, so I still don't see how this is "the best way in C++11". – Brian Bi Mar 02 '14 at 04:05
  • @BrianBi: It's not necessarily the best way, but it is the preferred alternative if you don't want to write two assignment operators (a move assignment operator and a copy assignment operator). If you only have one version which takes a const l-value reference, then that will be used for r-values as well, resulting in unnecessary copying operations in the body. This relies on the general assumption that moves should be cheap relative to copies. An assumption which should hold for most well designed classes. – Benjamin Lindley Mar 02 '14 at 04:09
  • @BrianBi This function will perform either no copy if the caller says `move`, or one copy, and either one or two move-construction operations. In practice though, move construction of a short-lived object can usually be eliminated by lifetime analysis. – Potatoswatter Mar 02 '14 at 04:49
0

Simple. Look at this code.

Student a, b;
a = b;

it is equal to

a.operator=(b);

and b is passed by value. so the copy constructor is called.

a.operator=(Student(b)); // please notice that it is just psudo code..

Therefore, there are two copying! One is copy constructor, and the other is copy assignment operator. It is unnecessary.


Moreover, copy constructor's param must be reference, too. Otherwise, the infinite recursion occurs because call-by-value requires copying and copying requires call-by-value and...

ikh
  • 10,119
  • 1
  • 31
  • 70