Effective C++ Item 28 避免返回对象内部数据的引用或指针

本文为senlie原创。转载请保留此地址:http://blog.csdn.net/zhengsenlie

Item 31

经验:避免返回handles(包含 references、指针、迭代器)指向对象内部。遵守这个条款可添加封装性,

帮助 const 成员函数的行为像个 const,并将发生“虚吊号码牌”(dangling handles)的可能性降至最低。

演示样例:

class Point{
public:
	Point(int x, int y);
	//...
	void setX(int newVal);
	void setY(int newVal);
	//...
};
struct RectData{
	Point ulhc;
	Point urhc;
}
class Rectangle{
public:
	//...
	Point &upperLeft() const {return pData->ulhc;} // bitwise constness --> const 函数仅仅保证成员变量的值不变,不保证成员变量指针所指的值不变
	Point &lowerRight() const {return pData->lrhc;}
	//...
private:
	std::tr1::shared_ptr<RectData> pData; // pimpl实现 --> Item 31
};

Point coord1(0,0);
Point coord2(100,100);
const Rectangle rec(coord1, coord2);
rec.upperLeft().setX(50); // rec 是个const 矩形,从(0,0)到(100,100)。但如今 rec 却变成 从(50,0) 到(100, 100)

解析:返回一个“代表对象内部数据”的handle,随之而来的便是“减少对象封装性”的风险。

不该令成员函数返回一个指针指向“訪问级别较低”的成员函数或成员变量,那样。后者的实际訪问级别就会提高如同前者。

纠正1:在返回类型加上 const

class Rectangle{
public:
	//...
	const Point &upperLeft() const {return pData->ulhc;}
	const Point &lowerRight() const {return pData->lrhc;}
	//...
};

解析:加了 const 后,尽管客户不能必然它们,但它还是可能导致 dangling handles:这样的handles所指东西不复存在。

演示样例:

class GUIObject (...);
const Rectangle boundingBox (const GUIObject &obj); //1.为什么以 by value 方式返回? 自己定义类型不是reference 更好吗? --> 由于 Rectangle 是 GUIObject的内部对象?
													//2.既然以by value返回,为什么还要加const,反正返回的是副本,客户改了也没关系呀?
GUIObject *pgo;
//...
const Point *pUpperLeft = &(boundingBox(*pgo).upperLeft()); //这条语句之后 boundingBox返回的对象被析构,间接导致该对象内的Points析构,终于导致 pUpperLeft指向一个不存在的对象

解析:handle比其所指对象更长寿

例外:operator[]会返回strings和vectors的个别元素,这些operator[]就是返回 reference 指向 “容器内的数据”

时间: 2024-10-06 03:17:49

Effective C++ Item 28 避免返回对象内部数据的引用或指针的相关文章

Effective C++ 条款28 避免返回handles指向对象内部成分

1. 所谓的handles指的是引用,指针,迭代器(可能与windows的句柄有所区别),返回一个handles会导致提供给用户对象内部数据的间接访问,这降低了成员变量的封装性,例如: class Demo{ public: ... int* getPtr() const { return ptr; } private: ... int* ptr; } 这段代码语法正确,但是它违背了将getPtr设为const的初衷:从语法上来说ptr所指对象也属于Demo对象的一部分,但从语法上讲,由于编译器

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

1. 虽然一般情况下传参使用const-by-reference-to-const比较好,但返回值有时必须是对象而不是引用: 当reference绑定到函数内创建的局部对象时,函数调用结束后引用绑定在一个不存在的对象; 当reference绑定到堆内存对象时,函数调用后比较容易忽略内存释放,特别对于以下表达式:w=x*y*z.如果operator*返回指向堆内存的引用,那没内存泄露是必然的; 当reference绑定到函数内部创建的static对象时,对于以下表达式if(a*b==c*d)由于返

Effective JavaScript Item 28 不要依赖函数的toString方法

本系列作为Effective JavaScript的读书笔记. 在JavaScript中,函数对象上存在一个toString方法,它能够方便地将函数的源代码转换返回成一个字符串对象. (function(x) { return x + 1; }).toString(); // "function (x) {\n return x + 1;\n}" toString方法不仅仅会让一些黑客找到攻击的方法,而且该方法也存在严重的限制. 首先,toString方法的实现方式并没有被ECMASc

Effective JavaScript Item 55 接受配置对象作为函数参数

接受配置对象作为函数参数 虽然保持函数接受的参数的顺序很重要,但是当函数能够接受的参数达到一定数量时,也会让用户很头疼: var alert = new Alert(100, 75, 300, 200, "Error", message, "blue", "white", "black", "error", true); 随着函数的不断重构和进化,它能够接受的参数也许会越来越多,最终就像上面的例子那样. 对

136.异常的多态,父类对象,传递子类的引用或指针(地址)

1 #include <iostream> 2 using namespace std; 3 4 //纯虚类 5 class error 6 { 7 public: 8 //纯虚函数 9 virtual void showerror() = 0; 10 }; 11 12 class big :public error 13 { 14 public: 15 void showerror() 16 { 17 cout << "big error" <<

Effective C++:条款28:避免返回 handles 指向对象内部成员

(一) 有时候为了让一个对象尽量小,可以把数据放在另外一个辅助的struct中,然后再让一个类去指向它.看下面的代码: class Point { public: Point(int x, int y); void setX(int newVal); void setY(int newVal); }; struct RectData { Point ulhc; Point lrhc; }; class Rectangle { public: Point& upperLeft() const {

[Effective C++ --028]避免返回handles指向对象内部成分

假设程序涉及矩形.每个矩形由其左上角和右下角表示.为了让Rectangle对象尽可能小,可能把定义矩形的点放在一个辅助的struct内再让Rectangle去指它: 1 class Point { // 得到坐标 2 public: 3 Point(int x, int y) {}; 4 void setX(int newVal) {}; 5 void setY(int newVal) {}; 6 }; 7 8 struct RectData 9 { 10 Point ulhc; 11 Poin

Effective C++ Item 46 需要类型转换时请为模板定义非成员函数

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:当我们编写一个 class template, 而它所提供之"与此 template 相关的"函数支持"所有参数之隐式类型转换"时,请将那些函数定义为 "class template内部的 friend 函数". 示例: template<typename T> class Rational{ public: Ration

Effective C++ Item 46 当需要投你非成员函数定义模板

本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:当我们编写一个 class template, 而它所提供之"与此 template 相关的"函数支持"全部參数之隐式类型转换"时.请将那些函数定义为 "class template内部的 friend 函数". 演示样例: template<typename T> class Rational{ public: Rati