为什么复制赋值运算符的参数应该是引用?

时间:2014-03-02 03:03:04

标签: c++ reference copy-assignment

“opperator =应该采用(当然,const最好)参考src obj的参数”,我在很多书中看到这一点,但我尝试使用非ref,它也有效!所以,是什么使用ref的目的是为了避免从param复制?我的测试代码是,

#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;
}

5 个答案:

答案 0 :(得分:1)

这里确实存在两个问题:

1)您已定义的副本分配运算符未被调用。这条线

Student dst=src;

不会调用复制赋值运算符!它调用复制构造函数,它由编译器隐式定义。但是,如果你写了

Student dst;
dst = src;

然后会调用operator=

2)是的,目的是避免复制。当您调用函数(包括operator=,其值为Student时,必须复制Student对象参数(通过对复制构造函数的隐式调用)。另一方面,如果该函数采用引用,则不进行复制。

答案 1 :(得分:1)

因为否则它将通过值传递,这是一个副本,因此您需要调用复制构造函数来调用复制构造函数...

答案 2 :(得分:0)

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

应该是

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

使用引用来避免浪费CPU

答案 3 :(得分:0)

在C ++ 03中,通过const引用可以避免为本地s创建一个可能非常昂贵的新副本,除了将s复制到目标对象。

在C ++ 11中,现在我们已经移动了语义:赋值可能导致资源转移到新对象或资源复制。可以利用pass-by-copy操作来生成用于目标对象的复制数据,从而充分利用开销。如果您使用move传递,则没有副本。 C ++ 11中的最佳实践是让单个函数同时作为复制和移动赋值运算符:

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

答案 4 :(得分:0)

简单。看看这段代码。

Student a, b;
a = b;

等于

a.operator=(b);

b按值传递。所以调用复制构造函数

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

因此,有两次复制!一个是复制构造函数,另一个是复制赋值运算符。没必要。


此外,复制构造函数的参数也必须是引用。否则,无限递归会发生,因为按值调用需要复制和复制需要按值调用和...