effective C++ 读书笔记 条款21

条款21 :必须返回对象时,别妄想返回其reference

条款20里面虽然说传引用比传值好用,但是不能传递一些 reference指向其实并不存在的对象

上代码:

#include <iostream>

using namespace std;

class Rational
{
public:
//	Rational()
//	{

//	}
	Rational(int m = 0, int n = 0 )
	{

	}
	~Rational()
	{

	}
private:
	int n, d;

	/*
	运算符重载形式有两种,重载为类的成员函数和重载为类的友元函数。 

	当运算符重载为类的成员函数时,函数的参数个数比原来的操作个数要少一个;
	当重载为类的友元函数时,参数个数与原操作数个数相同。原因是重载为类的成员函数时,
	如果某个对象使用重载了的成员函数,自身的数据可以直接访问,就不需要再放在参数表中进行传递,
	少了的操作数就是该对象本身。而重载为友元函数时,友元函数对某个对象的数据进行操作,
	就必须通过该对象的名称来进行,因此使用到的参数都要进行传递,操作数的个数就不会有变化。 

	*/
    friend const Rational operator*(const Rational& lhs, const Rational& rhs)
	{
		Rational temp;
		temp.n = lhs.n * rhs.n;
		temp.d = lhs.d * rhs.d;
		return temp;
	}
	/*
	这里为什么不能返回 const Rational& 呢?引文 temp是一个local对象,而local对象在函数退出的时候就销毁了,因此,如果
	这里返回const Rational&, 其实并没有返回reference指向某个Rational,它返回的reference指向一个"从前的"Rational,一个旧的
	Rational,一个曾经被当做Rational但是现在已经成空壳的残骸,因为它在函数退出的时候已经被销毁了。

	任何调用者甚至只是对此函数的返回值做任何一点点运用,都将立刻坠入"无定义行为"的恶地;

	总结:
	任何函数如果返回一个reference指向某个local对象,都将发生错误;
	任何函数如果返回一个指针指向一个local对象,结果也是一样的。

	*/
};

int main()
{

	Rational a(1,2);
	Rational b(3,5);
	Rational c = a*b;
	return 0;
}

/*
时间:2014年11月6日10:30:56
总结:绝对不要返回pointer或者reference指向一个local stack对象,或者返回reference指向一个
heap-allocated对象(不知道什么时候该调用delete),或者返回pointer或reference指向一个local static
对象而有可能同时需要多个这样的对象(那么同时使用多个对象的这个值都是等于这个 local static的值);

*/

再来一个例子:

#include <iostream>
using namespace  std;
class Test
{
public:
	Test()
	{

	}
	Test(int m) : i(m)
	{

	}
	~Test()
	{

	}
	friend const Test operator*(const Test& lhs,const Test& rhs);

public:
	int i;

};

// (1): 返回对象
const Test operator*(const Test& lhs,const Test& rhs)
{
	Test temp;
	temp.i = lhs.i*rhs.i;
	return temp;
}

// (2)返回引用
/*
const Test& operator*(const Test& lhs,const Test& rhs)
{
	Test temp;
	temp.i = lhs.i*rhs.i;
	return temp;
}
*/
int main()
{

	Test test1(3);
	Test test2(4);

	Test test3;
	test3 = test1*test2;
	cout<<test3.i<<endl;

//test3 = test1 * test2;
//	cout<<test3.i<<endl;

	return 0;
}

/*
当调用 (1)返回对象时,输出12
当调用 (2)返回引用时,输出一个乱码数字;可见,返回一个引用,其实它所指向的内容已经被释放,所以指向了一个内存当中空的地址;

*/
时间: 2024-09-29 10:38:54

effective C++ 读书笔记 条款21的相关文章

effective C++ 读书笔记 条款06

条款06:若不想使用编译器自动生成的函数,就该明确拒绝: 直接看代码与注释: #include <iostream> using namespace std; class Test { public: Test() { } ~Test() { } /* void TT() { Test t1; Test t2(t1); } */ private: Test(const Test& test); Test& operator = (const Test& test); }

Effective C++读书笔记(条款18-23)

(四).设计与声明 ____________________________________________________________________________________________________________________________________ 条款18:让接口容易被使用,而不容易被误用 #1.导入新类型可以让接口不易被误用,以函数替换对象则可以保证类型安全性. 例如: class Date{ public: Date(int month, int day

Effective C++读书笔记(条款24-29)

Effective C++第四篇,扩展的有点多... (四).设计与声明 ____________________________________________________________________________________________________________________________________ 条款24:若所有参数皆需类型转换,请为此采用non-member函数 #1.如果你需要为某个函数的所有参数(包括被 this指针所指的那个隐喻参数)进行 类型转

Effective C++读书笔记(条款1-10)

不得不说,Effective C++确实是一本C++进阶的好书,刚浏览完第二遍, 现对其做一个大体性的总结 ,并进行适当的展开,作为以后C++参考复习之用. (一).让自己习惯C++ ____________________________________________________________________________________________________________________________________ 条款1:视C++为一个语言联邦 #1.将C++ 分

effective C++ 读书笔记 条款20

条款20:宁以 pass-by-reference-to-const 替换 pass -by -value 1:采用后者效率高:看代码: #include <iostream> using namespace std; class Person { public: Person() { cout<<"Person()"<<endl; } Person(const Person& p) { cout<<"Person(co

effective C++ 读书笔记 条款11

条款11: 在operator= 中处理"自我赋值" 在实现operator=时考虑自我赋值是必要的就像 x=y .我们不知道变量x与y代表的值是否为同一个值(把x和y说成是一个指针更恰当一点). 例如以下 第一版: #include <iostream> using namespace std; class bitmap { public: bitmap() { cout<<"调用bitmap()无參构造函数"<<endl; }

effective C++ 读书笔记 条款08

条款08  别让异常逃离析构函数: 假设在析构函数其中发生了异常,程序可能会过早结束或者导致不明白行为(异常从析构函数传播出去) 看代码: #include <iostream> using namespace std; class DBConnection { public: void close() { int i = 3; int j = 0; int k = i/j; printf("%d\n",k); } }; class DBConn { public: DBC

effective C++ 读书笔记 条款12与条款13

条款12:确定你的public继承塑膜出is-a关系: 这个条款主要将了一些特殊情况:比如企鹅是鸟,企鹅可以继承于鸟,但是鸟会飞,企鹅却不能飞:还有让正方形继承矩形可能也会造成这种尴尬! 这个问题以前想过,但是不知道怎么解决,如果现实生活当中确实要这么使用:比如 猫 狗 鱼  猪等等许多动物继承Animal类,但是猫狗等不会游泳, 假如这里是有很多动物,不能采用鱼里面专门加一个方法!  这个现在还没想出来,条款12也没有讲如果要这么用该怎么处理就是将要避免这样. is - a; 在面向对象程序设

effective C++ 读书笔记 条款10

条款10:  令operator= 返回一个reference to *this; 关于赋值,我们可以这样写: int  x,y,x; x =y = z; 这就是所谓的连续赋值 为了实现"连锁赋值"赋值操作符必须返回一个reference指向操作符的左侧实参.这是我们为class实现赋值操作符时应该遵循的协议: #include <iostream> using namespace std; class Widget { public: Widget() { cout<