Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么复制赋值运算符的参数应该是引用?_C++_Reference_Copy Assignment - Fatal编程技术网

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

C++ 为什么复制赋值运算符的参数应该是引用?,c++,reference,copy-assignment,C++,Reference,Copy Assignment,“opperator=应该使用src obj的(当然,const best)ref的参数”,我在很多书中都看到了这一点,但我尝试使用非ref,它也可以!那么,使用ref的目的是什么?只是为了避免从param复制吗?我的测试代码是 #include <iostream> #include <string> using namespace std; class Student{ public: Student& operator=(Student);

“opperator=应该使用src obj的(当然,const best)ref的参数”,我在很多书中都看到了这一点,但我尝试使用非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;
}
#包括
#包括
使用名称空间std;
班级学生{
公众:
学生和操作员=(学生);
字符串名;
int-num;
};
学生和学生::运算符=(学生)
{
name=s.name;
num=s.num;
归还*这个;
}
int main(){
学生src;
src.name=“哈哈”;
src.num=11;
不能

应该是

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

在C++03中,使用引用可避免CPU的浪费,传递
const
引用可避免仅为本地
s
创建一个可能昂贵的新副本,除了将
s
复制到目标对象中之外,该副本永远不会被修改

在C++11中,现在我们有了移动语义:赋值可能会导致资源传输到新对象,或者资源复制。可以利用“按复制传递”操作生成用于目标对象的复制数据,因此可以充分利用开销。如果使用
move
传递,则没有复制。C中的最佳实践是++11是让一个函数同时作为复制和移动赋值运算符:

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

这里有两个问题:

1)您定义的复制分配操作符不会被调用

Student dst=src;
不调用复制赋值运算符!它调用由编译器隐式定义的复制构造函数。但是,如果

Student dst;
dst = src;
然后将调用
operator=


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

简单。请查看此代码

Student a, b;
a = b;
等于

a.operator=(b);
并且
b
通过值传递。因此调用复制构造函数

a.operator=(Student(b)); // please notice that it is just psudo code..
因此,有两个复制!一个是复制构造函数,另一个是复制赋值运算符。这是不必要的



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

因为否则它将按值传递,这是一个副本,所以您需要调用复制构造函数来调用复制构造函数…

构造函数标准中实际上有一条规则阻止您声明
X::X(X)
或类似的东西。@BrianBi当然,但我认为OP需要理由确实,我并不是想说你的答案中缺少什么。…..可能是一样的object@BrianBi:不,如果传递了一个r值参数,则不需要。在这种情况下,只需移动它。@BenjaminLindley点。但是,如果传递了一个左值,则需要一个副本将在调用函数时生成,而如果参数是引用,则该副本将被避免,因此我仍然不认为这是“C++11中的最佳方法”。@BrianBi:这不一定是最佳方法,但如果您不想编写两个赋值运算符,它是首选的替代方法(移动分配运算符和复制分配运算符)。如果只有一个版本采用常量l值引用,则该版本也将用于r值,从而导致正文中不必要的复制操作。这取决于一般假设,即相对于副本,移动应该便宜。这一假设适用于大多数设计良好的类。@BrianBi此函数将如果调用者说“移动”,则执行“不复制”,或者执行一个“复制”,以及一个或两个“移动构造”操作。但实际上,通过生存期分析通常可以消除短期对象的移动构造。“不复制”复制赋值运算符?它的目的是复制。@potatosatter我的意思是在调用函数mable replicate of时避免复制
a.operator=(Student(b)); // please notice that it is just psudo code..