C ++ getter方法的最佳实践是什么,它应该返回一个非平凡类型,但是类型为class或struct的成员。
MyType MyClass::getMyType() { return mMyType; }
const MyType& MyClass::getMyType() { return mMyType; }
MyType* MyClass::getMyType() { return &mMyType; }
,其中
class MyType { /* ... */ };
class MyClass
{
private:
MyType mMyType;
}
我特别担心这种方法的以下用法。如果function()
希望将其保存以供进一步使用,请您详细说明这可能会如何影响复制对象,以及悬挂引用和疯狂指针的危险。
MyType* savedPointer;
SomeType function(MyType* pointer) { savedPointer = pointer; };
一个。适用于1.和2.
{
MyType t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
湾适用于1.和2.
{
const MyType& t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
℃。适用于1.和2.
{
MyType& t = myClass.getMyType();
function(&t);
}
// is savedPointer still valid here?
d。有效期为3。
{
MyType* t = myClass.getMyType();
function(t);
}
// is savedPointer still valid here?
其中myClass
是MyClass
类型的对象。
答案 0 :(得分:19)
您可以提供const和非const版本:
MyType & MyClass::getMyType() { return mMyType; }
MyType const & MyClass::getMyType() const { return mMyType; }
我不会提供指针版本,因为这意味着返回值可能是空指针,在此实例中它永远不会出现。
然而,真正的一点是,您基本上是让调用者直接访问内部对象。如果这是您的意图,那么您也可以将数据成员公开。如果不是,那么你需要更加努力地隐藏对象。
一个选项是保留MyType const &
访问者,但提供更多间接方法来修改内部对象(setMyType(…)
或更适合您试图在语言级别表达的语义的内容。包含类)。
答案 1 :(得分:14)
一般情况下,除非您愿意,否则您应该更喜欢按值返回
明确地希望保证引用将指定
成员(公开部分实施,但是
在像std::vector<>::operator[]
)这样的情况下是可取的。返回
引用会阻止类中的后续更改,因为它意味着
你不能返回一个计算值。 (尤其如此
如果该类被设计为基类,则很重要
返回引用会为所有派生创建此限制
类。)
你应该通过指针返回的唯一时间是查找或 涉及的东西,可能返回必须返回 空指针。
返回对const的引用可能是有效的优化,如果 探查器指示此处的性能问题和呼叫 site也可以处理const引用(没有修改 返回值,对象的生命周期没有问题)。它 必须权衡额外的限制 当然,实施,但在某些情况下,这是合理的。
答案 2 :(得分:3)
我总是会返回一个const引用。如果您需要修改它返回的值,只需使用setter函数。
答案 3 :(得分:1)
应该避免按值返回,例如:MyType MyClass::getMyType() { return mMyType; }
,因为您将复制对象的内容。我没有看到你可以获得的收益,但我看到了性能上的弊端。
通过const引用返回:const MyType& MyClass::getMyType() { return mMyType; }
通常以这种方式使用:
const MyType& MyClass::getMyType() const { return mMyType; }
MyType& MyClass::getMyType() { return mMyType; }
始终提供const版本。非const版本是可选的,因为这意味着有人可以修改您的数据。这是我鼓励你使用的。
按地址返回:MyType* MyClass::getMyType() { return &mMyType; }
主要用于数据可选的地方。在使用之前通常需要进行检查。
现在,您的用例,我强烈建议不要将指针保存为超出范围。我经常会导致所有权问题。我必须这样做,看看shared_ptr。
对于您的示例,有两种情况:
一个。在结束括号后,savedPointer将不再有效。
b,c和d。 savedPointer在结束括号后有效,但要注意它不应该超过myClass
。
答案 4 :(得分:0)
a)MyType t =
将为1和2创建对象的副本。一旦t超出范围,保存的指针将无效。
b)保存的指针对于返回引用的情况有效,但对于返回对象的情况无效。作为参考,指针的生命周期与myClass相同。当然,const ref上的常量是常量*而不是t *,因此在调用function(MyType*)
时无法投射。
c)与b相同,但代码对2无效,因为您无法将const MyType&
强制转换为MyType&
。一般来说这是不好的做法,而且常量形式更容易接受。
d)savedPointer与myClass具有相同的生命周期。
我通常倾向于返回引用或const引用,具体取决于您希望能够对返回值执行的操作。如果返回引用(非const),则可以执行以下操作:myClass.getMyType() = ...
,而如果返回const引用,则该对象为只读。