【发布时间】:2010-06-26 22:39:49
【问题描述】:
相关:C++ private pointer "leaking"?
根据 Effective C++(第 28 条),“避免将句柄(引用、指针或迭代器)返回到对象内部。它增加了封装性,帮助 const 成员函数充当 const,并最大限度地减少了悬空句柄的创建。”
p>按值返回对象是我能想到的避免返回句柄的唯一方法。这对我来说表明我应该尽可能按值返回私有对象内部。
但是,要按值返回对象,这需要与“DISALLOW_COPY_AND_ASSIGN”运算符的Google C++ Style Guide 相悖的复制构造函数。
作为一个 C++ 新手,除非我遗漏了什么,否则我发现这两个建议相互冲突。
所以我的问题是:是否没有灵丹妙药可以让有效的引用返回到不受悬空指针影响的对象内部? const 引用返回是否尽可能好?另外,我应该不经常使用私有对象字段的指针吗?选择何时按值或按指针存储对象的私有实例字段的一般经验法则是什么?
(编辑)为澄清起见,Meyers 的示例悬空指针代码:
class Rectangle {
public:
const Point& upperLeft() const { return pData->ulhc; }
const Point& lowerRight() const { return pData->lrhc; }
...
};
class GUIObject { ... };
const Rectangle boundingBox(const GUIObject& obj);
如果客户端创建一个函数,代码如下:
GUIObject *pgo; // point to some GUIObject
const Point *pUpperLeft = &(boundingBox(*pgo).upperLeft());
“对 boundingBox 的调用将返回一个新的临时 Rectangle 对象 [(从这里调用 temp。)] upperLeft 然后将在 temp 上调用,并且该调用将返回对 temp 内部部分的引用,特别是,到组成它的点之一...在语句的末尾,boundingBox的返回值temp将被破坏,这将间接导致temp的点被破坏。反过来,这将使pUpperLeft指向一个对象那已经不存在了。” Meyers,Effective C++(第 28 条)
我认为他建议按值返回 Point 来避免这种情况:
const Point upperLeft() const { return pData->ulhc; }
【问题讨论】:
-
哦,那我不同意迈耶斯的观点。通过 const 引用而不是按值返回 Point 只是因为客户端可以滥用这些函数并且由于销毁 Rectangle 而使引用无效,这并不是按值返回所有内容的理由。在这种情况下,客户应该知道他需要返回的点的副本(当您通过 const 引用返回时他仍然可以这样做)。我最喜欢迈耶斯,但这本书已经有 12 年的历史了。在这种情况下,Sutter 会反驳他,并建议 Point 应该通过 const 引用返回 [...]
-
[...] 避免“悲观化”。然而,如果这就像一个窗口句柄被返回给一个控件,你通常希望避免返回它,因为它会放弃你的类维护不变量的能力。
标签: c++ pointers encapsulation