【问题标题】:Why are the initialization of a string from a function with std::string and std::string& similar?为什么用 std::string 和 std::string& 相似的函数初始化字符串?
【发布时间】:2020-05-15 03:45:15
【问题描述】:

考虑以下代码:

#include <string>
#include <sstream>

int main()
{
  const std::string name = "test test test";

  const std::string st = name.substr(0, 7);
  const std::string& st2 = name.substr(0, 7);
}

我知道理论上的差异,但查看汇编代码显示 -O2 根本没有差异。见下文:

st:

mov     ecx, 7
xor     edx, edx
lea     rdi, [rsp+32]
mov     rsi, rsp
call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::substr(unsigned long, unsigned long) const

st2:

mov     ecx, 7
xor     edx, edx
lea     rdi, [rsp+64]
mov     rsi, rsp
call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::substr(unsigned long, unsigned long) const

【问题讨论】:

  • 为什么你认为它会有所不同?引用的对象仍然必须调用该函数,并且由于它是const &amp;,因此它延长了临时对象的寿命。
  • 理论上有区别吗?
  • 您还期待什么?
  • 常量引用可以延长临时对象的寿命,就像按值返回的函数的结果一样。它的工作方式没有很好地定义,但大多数实现都会将该引用转换为场景背后的对象,并且对开发人员是不可见的。而且我认为这里的用户可能忘记了这种行为并不直观,第一次遇到时应该会感到惊讶。
  • 我知道理论上的差异”:我建议您添加一个解释,说明您认为理论上的差异是什么。考虑到这个程序在抽象机器上的行为,asm 对两行都做同样的事情并不奇怪。我认为您可能对理论差异有什么误解,或者您没有很好地传达您发现的令人惊讶的内容。

标签: c++ string assembly substring


【解决方案1】:

在初始化st的情况下,因为copy elision,所以直接将name.substr的返回值构造成名为st的字符串对象。在st2的情况下,返回值被直接构造成一个未命名的临时对象,st2被初始化为对该未命名对象的引用。

在这两种情况下,name.substr 的结果都被构造成一个自动存储持续时间的对象,该对象位于 main 本地,无需复制或移动。唯一的区别是该对象在第一种情况下有名称,而在第二种情况下没有。编译器没有理由为创建这两个对象生成不同的代码。

(将临时对象绑定到 const 引用也延长了临时对象的生命周期,使临时对象具有与 st 相同的生命周期。这实际上使临时对象名称为 st2,使其与命名的对象实际上相同st。但是,由于这是在函数的最后一条语句中完成的,因此在您的示例中没有显着影响。)

【讨论】:

  • 如果我们在没有优化的情况下进行编译,我希望构造函数调用之后的代码会有所不同。 std::string&amp; st2 是对对象的引用,因此我们希望 movlea rdi, [rsp+64] 指针存储到堆栈上的 8 字节位置。使用st,命名对象 字符串,因此无需在任何地方存储指向它的指针。 (启用优化后,实际上将st2 指针存储在任何地方可能都会被优化掉。)
  • @PeterCordes 没有优化,有一个参考商店,是的,但我不知道这在这里是否重要,因为原始发布者正在谈论使用优化进行编译。
  • 对。我的观点是,就 C++ 抽象机(ry)而言,源代码行并不是 100% 相同的,并且它们仅编译相同,因为参考的一部分已被优化掉。以防所有未来的读者都不清楚您的措辞方式。但是,是的,同意没有理由为 创建 两个 std::string 对象使用不同的 asm。
猜你喜欢
  • 2018-03-21
  • 2016-03-26
  • 2016-05-08
  • 1970-01-01
  • 2016-02-04
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 2013-09-12
相关资源
最近更新 更多