假设 Foo
是一个相当大的数据结构。如果我不知道继承类是否会在内部存储 Foo
的实例,那么我应该如何编写一个返回 Foo
实例的 const
虚函数?如果无法在内部存储它,我的理解是无法返回一个 const
引用,因为它将是一个临时变量。这正确吗?两个选项是:
virtual Foo foo() const { ... }
virtual Foo const & foo() const { ... }
这里有一个相关问题,但是从不同的角度来看。
假设 Foo
是一个相当大的数据结构。如果我不知道继承类是否会在内部存储 Foo
的实例,那么我应该如何编写一个返回 Foo
实例的 const
虚函数?如果无法在内部存储它,我的理解是无法返回一个 const
引用,因为它将是一个临时变量。这正确吗?两个选项是:
virtual Foo foo() const { ... }
virtual Foo const & foo() const { ... }
这里有一个相关问题,但是从不同的角度来看。
您对值返回和const引用返回之间的区别感兴趣,仅仅是出于优化的考虑,但实际上不是这样的。每次返回不同的值与每次返回引用有根本上不同的含义,可能是对同一对象的返回引用,该对象很可能被修改:
const Foo &a = myobj.foo();
myobj.modify_the_foo();
const Foo &b = myobj.foo();
a == b; // do you want this to be true or false?
我看到你没有将C++0x列为一个标签,但是对于任何有需要并且可以访问C++0x的人来说,也许最好的方法是返回一个std::unique_ptr<>
。
unique_ptr
类型,因为这是不可能的,除非使用C++11,在那里已经有了标准的unique_ptr
。在C++03中,如果您想返回一个没有引用计数的智能指针,则可以使用auto_ptr
。 - Dennis Zickefoosestruct K
{
int ii;
};
class I
{
virtual K &get_k(int i)=0;
};
class Impl : public I
{
K &get_k(int i) { kk.ii = i; return kk; }
K kk;
};
它的工作原理在于您在同一对象中使用K kk; 作为数据成员。Impl类的构造函数也可能很有用。
编辑:更改代码格式
如果您不知道派生类是否可以存储对象,则不能通过引用返回。因此,对于您的问题的严格答案是必须通过值返回。
其他答案建议返回指针或智能指针,这也可以工作。但是,那么不存储对象的客户端将不得不执行动态分配,这可能比移动或复制甚至是相当大的对象更慢。
如果您的主要关注点是避免复制,则可以通过使接口稍微不那么好看来实现:
virtual void foo(Foo& putReturnvalueHere) const { ... }
将之前要返回的值分配给传入的引用。这需要Foo已经被构造。如果这不可接受,您可以传递一个指向未构造内存区域的指针,该区域将保存一个Foo,然后使用放置new来在该内存区域中构造一个Foo:
virtual void foo(Foo* unconstructedFoo) const { ... }