在这种情况下的值或引用语义?
-
09-10-2019 - |
题
我对在某些情况下是否选择值语义或引用语义没有感觉(但我希望如此)。有什么我可以应用的经验法则吗?
我通常会选择除内置数据类型(char、int、bool、double 等)以外的所有内容的引用。但是,有时无法从函数返回引用,因此我必须使用指针。下面的函数就是一个例子:
Foo bar()
{
Foo f;
f.do_stuff();
return f;
}
我会使用 boost::shared_ptr 来存储 Foo 对象,但这使得使用该对象变得非常难看。我目前正在研究一个返回双端队列的函数,该双端队列几乎不会超过 10 个元素(这是我的假设,我无法确定)。按值返回可以吗?我的考虑是否属于过早优化的情况?
解决方案
按值返回是可以的,因为大多数编译器都会优化额外的副本(这称为返回值优化,或者在您的情况下命名为返回值优化)。
但是惯用方式是
void bar(Foo& out)
{
out.do_stuff();
}
其他提示
无论如何,不要 返回 堆栈上分配的任何内容(即局部变量,例如这里的 f)通过引用或指针。
您可以随时这样做:
Foo& bar(Foo& f)
{
f.do_stuff();
return f;
}
并这样使用:
Foo f;
bar(f);
这里的缺点是您不能保证 bar()
将收到新的 Foo
目的。如果这很重要,则必须对此进行修改:
Foo& bar(Foo& f)
{
f = Foo();
f.do_stuff();
return f;
}
但是,如果确实获得了新副本,则将有不必要的初始化。或者,您可以简单地检查 f
前 doSomething()
如果不符合期望,请提出异常。
当您想维护任何变量或对象的状态时使用参考(即通过调用例程在变量/对象上完成某些procesisng之后,将相同的变量与调用例程进行相同的变量),并且在将大数据传递给功能否则将有大量数据的双副本。
同样,在某些情况下,需要防止对象复制位,在这种情况下,我们将类的复制构造函数作为私有。
我的正常规则是:
始终按价值使用通过。
简单,嗯?参考吸吮。他们永远不应该引入。
如果您有“类似数据结构”,则将其传递。如果您有“类似数据结构”的“对象”传递指针(参考语义,请按值传递)。
通常很清楚哪种类型是:值或对象。如果您可以将其变异,它是一个对象。