在C ++中返回string的最好方法是什么?

我的问题很简单:如果我有一个类Man,并且想定义返回人名的成员函数,我更喜欢以下两个变体中的哪一个?

第一:

string name(); 

第二:

 void name(/* OUT */ string &name); 

第一个变种是低效的,因为它会产生不必要的拷贝(局部variables – >返回值 – >赋值左边的variables)。

第二个变种看起来非常有效,但是这让我哭了

 string name; john.name(name); 

而不是简单

 string name(john.name()); 

那么,我更喜欢什么样的变体,效率和方便性/可读性之间有什么合适的取舍?

提前致谢。

这是一个很好的问题,而且你问的事实表明你正在关注你的代码。 不过,好消息是,在这个特殊情况下,有一个简单的办法。

第一,干净的方法是正确的做法。 编译器会在大多数情况下(通常在有意义的地方) 消除不必要的副本 。

编辑(6/25/2016)

不幸的是,David Abaraham的网站似乎已经离线了好几年了,而这篇文章已经被输给了ethers(没有archive.org的副本)。 为了档案的目的,我冒昧地把本地副本上传为PDF格式, 可以在这里find 。

使用第一个变体:

 string name(); 

编译器很可能会优化任何不必要的副本。 请参阅返回值优化 。

在C ++ 11中,移动语义意味着即使编译器不执行RVO,也不会执行完整的副本。 请参阅移动语义 。

另外请记住,如果替代scheme是

 void name(std::string& s); 

那么你必须非常清楚地指定s可能发生的事情,以及它传递给函数时可能具有的值,可能要么进行大量的有效性检查,要么完全覆盖input。

既然你想为你的类的字段创build一个getter,也许你应该这样做: inline const std::string& name() const { return this->name; } inline const std::string& name() const { return this->name; }

由于该名称是作为一个const引用返回的,因此它不会在类外被修改,也不会通过返回名称来创build副本。

之后,如果你想操纵这个名字,你将不得不做一个副本。

我会去的第一个。 返回值优化和C ++ 11将删除任何复制开销。

由于我们有移动语义(在C ++ 11中),你可以使用这个:

 string name(); 

即使在C ++ 03中,这也几乎是不错的,因为编译器可能会优化它( search返回值优化 )。

优化规则1: 测量 ,优化,测量。 或者,正如Knuth所说,“不成熟的优化是万恶之源”。

除非你有强烈的暗示,简单的返回std::string会显着影响你的软件的性能,只要这样做。 如果您可以衡量重大影响,find关键path,并优化。 不要做任何有趣的项目范围的“优化”,这可能会导致很less或没有性能好处,但会对代码的可读性,可维护性和健壮性产生负面影响。

我认为你应该使用第一个变种。 因为这是简单的getter方法,并且这种getter / setter方法被使用到处。