我的问题很简单:如果我有一些类Man,我想定义返回man名称的成员函数,我更喜欢以下两种变体中的哪一种?
第一:
string name();
Run Code Online (Sandbox Code Playgroud)
第二:
void name(/* OUT */ string &name);
Run Code Online (Sandbox Code Playgroud)
第一个变体是低效的,因为它会产生不必要的副本(局部变量 - >返回值 - >赋值左侧的变量).
第二个变体看起来非常有效,但它让我哭泣
string name;
john.name(name);
Run Code Online (Sandbox Code Playgroud)
而不是简单
string name(john.name());
Run Code Online (Sandbox Code Playgroud)
那么,我更喜欢哪种变体,以及效率和便利性/可读性之间的适当权衡是什么?
提前致谢.
Mah*_*dsi 52
这是一个很好的问题,而且你问它的事实表明你正在关注你的代码.然而,好消息是,在这种特殊情况下,有一个简单的方法.
第一个干净的方法是正确的方法.在大多数情况下(通常在有意义的地方),编译器将消除不必要的副本.
编辑(2016年6月25日)
不幸的是,似乎David Abaraham的网站已经离线了几年了,而且这篇文章已经遗失给了ethers(没有archive.org副本可用).我冒昧地将我的本地副本上传为PDF用于存档目的,可在此处找到.
jua*_*nza 25
使用第一个变体:
string name();
Run Code Online (Sandbox Code Playgroud)
编译器很可能会优化出任何不必要的副本.请参阅返回值优化.
在C++ 11中,移动语义意味着即使编译器不执行RVO也不会执行完整拷贝.请参阅移动语义.
还要记住,如果替代方案是
void name(std::string& s);
Run Code Online (Sandbox Code Playgroud)
那么你必须非常清楚地指明s传递给函数时会发生什么以及它可以具有什么值,并且可能要么进行大量的有效性检查,要么只是完全覆盖输入.
既然你想为你的班级领域创建一个getter,也许你应该这样: inline const std::string& name() const { return this->name; }
由于该名称作为const引用返回,因此不会在类外部进行修改,也不会通过返回名称来创建副本.
之后,如果您想操纵名称,则必须进行复制.