在 C++11 中,我们被引导在某些情况下通过值传递对象,而在其他情况下通过 const-reference 传递对象。然而,这个指导方针取决于方法的实现,而不仅仅是它的接口和它的客户的预期用途。
当我写一个接口时,我不知道它会如何实现。编写方法签名是否有一个好的经验法则?例如 - 在下面的代码片段中,我应该使用Bar1
orBar2
吗?
class IFoo
{
public:
virtual void Bar1(std::string s) = 0;
virtual void Bar2(const std::string& s) = 0;
};
如果您同意正确的签名取决于实现,您可以停止阅读此处。这是一个例子,说明了我为什么这么认为。
在以下示例中,我们应该按值传递字符串:
class Foo
{
std::string bar;
Foo(std::string byValue)
: bar(std::move(byValue))
{
}
};
现在我们可以在所有情况下以有效的方式实例化 Foo:
Foo foo1("Hello world"); // create once, move once
Foo foo2(s); // the programmer wants to copy s. One copy and one move
Foo foo3(std::move(t)); // the programmer does not need t anymore. No copy at all
在其他情况下,我们更喜欢通过 const 引用传递对象。例如,在以下情况下,我们不想复制/存储参数,只需使用它的方法:
void DoStuff(const std::string& byRef)
{
std::cout << byRef.length() << std::endl;
}
上述方法的所有可能用法已经尽可能高效。
更新
我相信我忘了展示 const-reference 替代方案的问题。如果上面的类Foo
是这样实现的:
class Foo
{
std::string bar;
Foo(const std::string& byRef)
: bar(byRef)
{
}
};
那么我们会得到以下结果:
Foo foo1("Hello world"); // Here we would have one more copy of the string. It is less efficient.
Foo foo2(s); // One copy, like before
Foo foo3(std::move(t)); // Irrelevant here.
亚历克斯。