为类重载赋值运算符返回引用值是为了连续赋值?

header_zj 2016-06-02 11:14:52
我想问一下为什么类的重载赋值运算符返回值必须是引用值,之前听说是为了连续赋值?我不太懂
class A
{
public:
A(int i){x=new int;*x=i;}
// A(A&r){x=new int;*x=r.get();}
~A(){delete x;x=NULL;}
void set(int i){*x=i;}
int get(){return *x;}
A operator=(A&r)
{
*x=r.get();
return *this;
}
private:
int *x;
};

PS:不加引用说明符会出现下面warnig:

||=== Build: Debug in oooo (compiler: GNU GCC Compiler) ===|
|In function 'int main()':|
|error: no match for 'operator=' (operand types are 'A' and 'A')|
|note: candidate is:|
|note: A A::operator=(A&)|
|note: no known conversion for argument 1 from 'A' to 'A&'|
...全文
272 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
header_zj 2016-06-03
  • 打赏
  • 举报
回复
引用 7 楼 qq423399099 的回复:
以下几种情况调用拷贝构造: 1当用类的一个对象初始化该类的另一个对象时. 2 如果函数的形参是类的对象,调用函数时,进行形参和实参结合时. 3 如果函数的返回值是类的对象,函数执行完成返回调用者时. 4、需要产生一个临时类对象时。 楼主第一和第二个问题就是上面的第二种和第三种情况 第三个问题,楼主在析构函数里打印一下,然后单步调试你就知道了 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
道理我懂,我加了一些语句
class A
{
public:
	A(int i){x=new int;*x=i;cout << "A(int i)operated" << endl;}
//	A(A&r){x=new int;*x=r.get();}
	~A(){delete x;x=NULL;cout << "~A()operated"<< endl;}
	void set(int i){*x=i;}
	int get(){return *x;}
	A& operator=(A&r)
	{
		*x=r.get();
		return *this;
	}
private:
	int *x;
};
并且调试这个main函数的时候
int main()
{
    A a(1), b(2), c(3);    //(1)
    a = b = c;   //(2)
    cout << a.get() << b.get() << c.get();  //(3)
}
我发现在运行完第(3)行输出的时候会跳到(1)然后调用两次析构函数,再重新跳到(3)然后又调用了一次析构函数,我不太懂
小灸舞 2016-06-03
  • 打赏
  • 举报
回复
以下几种情况调用拷贝构造:
1当用类的一个对象初始化该类的另一个对象时.
2 如果函数的形参是类的对象,调用函数时,进行形参和实参结合时.
3 如果函数的返回值是类的对象,函数执行完成返回调用者时.
4、需要产生一个临时类对象时。

楼主第一和第二个问题就是上面的第二种和第三种情况
第三个问题,楼主在析构函数里打印一下,然后单步调试你就知道了

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
header_zj 2016-06-03
  • 打赏
  • 举报
回复
引用 4 楼 qq423399099 的回复:
一、c/c++赋值运算符的本意为“返回左值的引用”(左值:赋值号左面的变量而非其值) 对于a = b(a,b均为对象时),若不返回左值的引用,将会生成临时对象。如果不处理a = b = c这样的表达式,也会正常(只是会调用拷贝构造函数和析构函数处理临时对象)。 二、为了进行连续赋值,即 x = y = z PS:也并非必须返回引用,返回引用的好处既可以于赋值的原始语义已知,又可避免拷贝构造函数和析构函数的调用
(一)请问一下给函数利用值传递的方式传实参的时候,比如说实参是一个类类型,那么是通过拷贝构造函数还是赋值构造函数传值的。 (二)return 的时候如果是直接传值那么是通过拷贝构造函数还是赋值构造函数呢 (三)鉴于您所说的连续赋值的问题(x=y=z),如果我赋值构造函数返回值是A而不是A&的时候产生的临时变量的生存期为多长,什么时候调用自己的析构函数呢,谢谢!
paschen 版主 2016-06-03
  • 打赏
  • 举报
回复
1、两个都对,但但可以直接写成int a[100] = {0}; 就可以达到你要效果 2、类对象不建议使用memset,除非你可以确保这个类是个POD,否则建议直接在构造函数中进行初始化
小灸舞 2016-06-03
  • 打赏
  • 举报
回复
一、c/c++赋值运算符的本意为“返回左值的引用”(左值:赋值号左面的变量而非其值)
对于a = b(a,b均为对象时),若不返回左值的引用,将会生成临时对象。如果不处理a = b = c这样的表达式,也会正常(只是会调用拷贝构造函数和析构函数处理临时对象)。

二、为了进行连续赋值,即 x = y = z

PS:也并非必须返回引用,返回引用的好处既可以于赋值的原始语义已知,又可避免拷贝构造函数和析构函数的调用
paschen 版主 2016-06-03
  • 打赏
  • 举报
回复
不加&也可以,只是按值传递效率比较低 另外你喜欢的话甚至可以不是A类型,而是其他任意类型,如int、double...
lqbk1 2016-06-02
  • 打赏
  • 举报
回复
此外,还需保证类似这样的代码结果是唯一的。 所以你只能按规定去做,否则就出乱子
#include<iostream>
using namespace std;

class A
{
public:
	A(int i){x=new int;*x=i;}
	//    A(A&r){x=new int;*x=r.get();}
	~A(){delete x;x=NULL;}
	void set(int i){*x=i;}
	int get(){return *x;}
	A& operator=(A&r)
	{
		*x=r.get();
		return *this;
	}
private:
	int *x;
};

int main()  
{   
	A a(1),b(2);
	(a=b).set(3);
	cout<<a.get()<<endl;
	return 0;  
}  
lqbk1 2016-06-02
  • 打赏
  • 举报
回复
这是规定,主要是为了下面这样的代码能够执行且能够高效执行

A  a,b,c;
a=b=c;

65,183

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧