在C++中返回字符串的最佳方法是什么?

ton*_*ony 64 c++ string

我的问题很简单:如果我有一些类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用于存档目的,可在此处找到.

  • +1链接到戴夫亚伯拉罕的优秀文章. (3认同)

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传递给函数时会发生什么以及它可以具有什么值,并且可能要么进行大量的有效性检查,要么只是完全覆盖输入.


Mes*_*sop 9

既然你想为你的班级领域创建一个getter,也许你应该这样: inline const std::string& name() const { return this->name; }

由于该名称作为const引用返回,因此不会在类外部进行修改,也不会通过返回名称来创建副本.

之后,如果您想操纵名称,则必须进行复制.

  • 是的,在这种情况下,您将不得不返回该值,因为从函数返回后对局部变量的引用将无效.问题的另一个替代方法是每次修改名字或姓氏时计算全名(您可以在`setName`或`setFirstName`方法中执行此操作)并将其存储在fullname字段中.这样,每次调用`fullname()`时都不必重新计算全名,只需将const引用返回到fullname字段(如我的答案中所述). (2认同)

flu*_*mpb 5

我会选择第一个.返回值优化和C++ 11将删除任何复制开销.