我应该返回std :: strings吗?

Ped*_*ino 65 c++ string return-value

我试图使用std::string而不是char*尽可能使用,但我担心我可能会降低性能.这是返回字符串的好方法(为简洁起见,没有错误检查)吗?

std::string linux_settings_provider::get_home_folder() {
    return std::string(getenv("HOME"));
}
Run Code Online (Sandbox Code Playgroud)

另外,一个相关的问题:当接受字符串作为参数时,我应该接收它们const std::string&还是const char*

谢谢.

duf*_*ymo 63

返回字符串.

我认为更好的抽象是值得的.在你能衡量一个有意义的性能差异之前,我认为这是一种微观优化,只存在于你的想象中.

花了很多年才把一个好的字符串抽象化到C++中.我不相信Bjarne Stroustroup,因其保守的"只为你使用的东西买单"而闻名,可能会让这种语言成为明显的表演杀手.更高的抽象是好的.

  • 我不认为让完美成为善的敌人是一个明智的策略.等待完美的软件不是答案. (12认同)
  • "在C++中获得良好的字符串抽象花了很多年." 恕我直言,它仍然很糟糕. (4认同)
  • 请记住,您也可以在适当的地方使用引用,以避免不必要的副本.我尝试在可能的情况下将输入参数设置为"const std :: string&" (3认同)

Ste*_*sop 14

像所有人所说的那样返回字符串.

当接受字符串作为参数时,我应该接收它们const std::string&还是const char*

我会说通过引用获取任何const参数,除非它们具有足够的轻量级以获取值,或者在极少数情况下需要空指针作为有效输入意味着"以上都不是".此政策并非特定于字符串.

非const引用参数是有争议的,因为从调用代码(没有一个好的IDE),你不能立即看到它们是通过值还是通过引用传递,并且差异很重要.所以代码可能不清楚.对于const params,这不适用.阅读调用代码的人通常可以假设这不是他们的问题,所以他们只是偶尔需要检查签名.

如果您要在函数中获取参数的副本,则一般策略应该是按值获取参数.然后你已经有了一个你可以使用的副本,如果你将它复制到一个特定的位置(比如数据成员)那么你可以移动它(在C++ 11中)或交换它(在C++ 03中)到把它弄到那里.这为编译器提供了优化调用者传递临时对象的最佳机会.

对于string特别是,这覆盖了您的函数有一个的情况下std::string通过值,调用者指定作为参数表达字符串文字或一个char*指向一个空终止字符串.如果您const std::string&在函数中使用并复制它,则会导致构造两个字符串.


jsk*_*ner 12

按值复制字符串的成本因您正在使用的STL实现而异:

  • MSVC下的std :: string使用短字符串优化,因此短字符串(<16个字符iirc)不需要任何内存分配(它们存储在std :: string本身中),而较长的字符串需要堆分配每次复制字符串.

  • GCC下的std :: string使用引用计数实现:当从char*构造std :: string时,每次都进行堆分配,但是当通过值传递给函数时,引用计数只是增加,避免了内存分配.

一般来说,你最好忘记上面的内容并按值返回std :: strings,除非你每秒做数千次.

re:参数传递,请记住,从char* - > std :: string开始会有成本,但不会从std :: string-> char*开始.一般来说,这意味着你最好接受对std :: string的const引用.然而,接受const std :: string&作为参数的最佳理由是,然后被调用者不必具有用于检查与null的额外代码.


kos*_*tia 10

似乎是个好主意.

如果这不是实时软件(如游戏)的一部分,而是常规应用程序,那么你应该更好.

请记住," 过早优化是所有邪恶的根源 "


Aar*_*reP 6

担心性能是人的本性,特别是当编程语言支持低级优化时.作为程序员,我们不应该忘记的是,程序性能只是众多我们可以优化和欣赏的一件事.除了程序速度,我们可以在自己的表现中找到美感.我们可以尽量减少我们的努力,同时努力实现最大的视觉输出和用户界面互动性.你是否认为这可能是更长时间担心比特和周期的动机......所以是的,返回字符串:s.它们可以最大限度地减少您的代码大小和您的工作量,并使您的工作量减少.


Kir*_*sky 5

在您的情况下,将发生返回值优化,因此不会复制std :: string.

  • +1:你说得对.如果没有RVO,则必须分配两个缓冲区并在它们之间进行复制. (3认同)