C++ 常量字符串a=";tmp“;vs常量字符串&;a=";tmp“;

C++ 常量字符串a=";tmp“;vs常量字符串&;a=";tmp“;,c++,string,optimization,C++,String,Optimization,我和我的一位同事就这个问题进行了讨论。想知道更多人对哪一个“可以”更为理想的看法吗? PS:如果代码只是一个Hello World程序,-O3会产生相同的代码,但是我们正在讨论一个场景,这个代码段位于一个大项目的中间。你的档案员可能会告诉你不要担心 在这种情况下,无论如何都必须构造一个新的std::string,而“const reference to life time extended temporary value”实际上只会导致编译器做更多的工作(发出等效/相同的代码) 我会选择清晰:

我和我的一位同事就这个问题进行了讨论。想知道更多人对哪一个“可以”更为理想的看法吗?
PS:如果代码只是一个Hello World程序,-O3会产生相同的代码,但是我们正在讨论一个场景,这个代码段位于一个大项目的中间。你的档案员可能会告诉你不要担心

在这种情况下,无论如何都必须构造一个新的
std::string
,而“const reference to life time extended temporary value”实际上只会导致编译器做更多的工作(发出等效/相同的代码)

我会选择清晰:

代码意图,而不是方法 所以


可能编译器会生成相同的代码,但使用引用会误导普通读者。考虑一下,不是用文字初始化它,而是使用函数返回:

std::string f();

std::string const & r = f(); // [1]
标记为[1]的行似乎只是在创建对其他地方管理的对象的引用(低成本操作)。代码的读取器将试图弄清楚引用的字符串是否可以在外部更改,或者即使它可能会被销毁,也会留下一个悬空的引用。他们必须查阅
f()
的文档,找出它实际上是一个临时代码,然后回到原始代码,找出这只是一些程序员在耍聪明的把戏

另一方面,
std::string s=f()
的意图更加明确:无论
f()
代表什么,都将在本地上下文中维护它的副本。对象不会在外部更改,并且其生存期正是定义它的范围


请注意,在这两种情况下,行为实际上是相同的,但在一种情况下,这对普通读者来说是显而易见的,而在另一种情况下,读者必须弄清楚这一点。在所有的情况下,我都会使用本地对象,并将生命周期的扩展限制在一些值不会减少的情况下(这在现实生活中我只需要一次)。什么使你认为优化器在你的Hello World程序中比在一个大项目的中间处理这个不同?代码>或甚至
字符a[]=“tmp”这可能会更快;)关键不是让代码快速。我们都同意这两个都没有用。这只是一个讨论:)@nightcracker我不确定,但记录压力和更多的优先顺序/优化指示可能会导致一些差异。我不是这方面的专家,如果我错了,请纠正我。我也喜欢这种方法的角度:基本相同:表达意图,但这一次,更多地关注人类读者+1感谢您的输入。我理解使代码对其他人可读的重要性。但是从完全个人的角度来看,我觉得从函数返回std::string不是最好的方法。原因函数可以返回一个非常长的字符串,这对于创建本地副本没有任何意义。如果调用者和被调用者对这样一个字符串的长度有明确的约定,这可能会很好。@Game:你的假设是错误的。如果您要返回对现有
std::string
的引用,那么是的,按值返回时成本会更高。但是,如果要在函数中创建
std::string
,则必须按值返回它。在大多数情况下,多余的副本将被省略(即在函数中创建的字符串和返回的字符串将是同一个对象),当这不可能时(仅在C++11中),内容将被移动,这是一种低成本的操作。例如,当代码应用到字符串时,它会按值返回。如果函数返回引用,则保持引用是有意义的,但是如果函数按值返回,则应该将其存储在本地对象中,而不使用生存期扩展HACK。请注意,这是答案中的要点:不要关注
f()
的设计,而是给定一个按值返回的
f()
,在调用站点上使用哪个选项。很抱歉打扰您(如果是),如果函数返回的是本地构造的值,我相信获得签名的最佳方法是void/bool-fun(string*a);而不是string fun();同样,可读性必须受到损害。我知道复制省略,但我觉得如果我们可以通过签名避免它,我们应该这样做。你可以依靠编译器优化,而不是依赖它们。
std::string tmp = "Hello"; 
std::string f();

std::string const & r = f(); // [1]