在 非模板 类中,是否有理由更喜欢const <type>& foo();
与<type> foo();
形式的函数返回签名? <type>
是一种内在类型。如果<type>
是类/结构对象呢?
同样感兴趣的是 const 这个函数是否有所不同:const <type>& foo() const;
到<type> foo() const;
E.g。在非模板类中,非模板函数:
const int& foo() const { return member_variable_; }
Versus
int foo() const { return member_variable_; }
答案 0 :(得分:3)
对于基本类型,只需按值返回。没有理由通过const引用返回原语。
对于非原始类型,它取决于。
如果返回的值是函数的局部变量,则必须按值返回。否则,在调用者使用返回的引用之前,该变量将被销毁。
如果返回的值是类数据成员,那么您可以选择。
通过const引用返回可以避免副本,这可能是性能优势。但是,它将您的接口与实现联系起来,即数据成员和返回值必须是相同的类型。它也不太安全,因为调用者可以保留引用的时间长于对象的生命周期,例如:
const X& x = y->foo();
delete y;
// use x, oops!
按值返回会产生一个或两个副本,具体取决于您是否可以利用返回值优化(这可能适用于简单的get()方法)。此外,可以更有效地复制使用默认复制构造函数的对象副本(想一想:编译器可以简单地记忆数据)。
建议:以值返回开始,并在确定该调用/副本已知是性能问题后切换到const引用返回。
最后,另一种方法是通过参数返回,这对于更复杂的对象(例如字符串)非常有用:
void foo(X& return_val) { return_val = member_variable_; }
或:
void foo(X* return_val) {
assert(return_val != 0);
*return_val = member_variable_;
}
答案 1 :(得分:0)
如果需要返回一个值,则必须返回一个值 - const引用不是可接受的替代。但我怀疑你问的是这样的事情:
struct A {
X x;
...
X f1() { return x; }
const X & f2() { return x; }
};
我从来没有为此提出过万无一失的准则。
答案 2 :(得分:0)
这完全取决于您想要做什么。
如果要返回对用户代码使用的对象的引用,则:
<type>& foo() { ... }
如果要以只读方式返回对象的引用,只允许访问此对象类型的const函数,则:
const <type>& foo() { ... }
如果要返回对用户代码要使用的对象的引用,即使该类实例仅以只读方式使用(作为const),则:
<type>& foo() const { ... }
如果你想要以只读的方式返回对象的引用,只允许访问这个对象类型的const函数,并且如果类实例只在read(as const)中使用,那么事件:
const <type>& foo() const { ... }
只是要添加一个警告:不要返回对函数变量的引用,它们不能在函数外运行...
答案 3 :(得分:0)
const <type>& foo();
您的类中可能有类似容器元素的资源,而foo()
会返回特定元素,如果您知道资源可用的时间足够长,您可能会返回对容器中元素的const引用,这样就可以避免不必要的分配/复制数据。
它可能是const
,取决于您处理数据的方式,如果您不希望通过foo()
返回的引用修改数据,那么将其设为const。也许你有一个案例,你想要修改资源和一些额外的工作需要完成,你会使非const。您可以在api用户中同时选择基于用例。
<type> foo();
返回资源<type>
的新副本。这意味着要制作副本。这对于简单数据或可能共享值的情况很有用,并且您希望确保<type>
的每个实例都是独立的 - 非共享,如某些字符串或int。
答案 4 :(得分:0)
如果类型是固有类型,则传递const refs不会提高性能,并且可能会降低性能,并且安全性较低;最好是按值传递和返回。我不是一个ASM人,但据我所知,通过引用返回意味着该值无法存储在寄存器中,因为它需要一个返回地址,因此可以禁用一些其他有用的优化;我对此并不积极。
如果是类或结构,则取决于值的生命周期;如果它是函数的局部函数则无法返回,否则,如果它是类成员,我更喜欢const类型&amp;返回因为它可以通过避免复制构造函数提供更好的性能。 (意见不同,因为by值被认为更安全)。它还使您不必实现复制构造函数或使用潜在的恶意默认值,这很好。