2017-06-01 59 views
6

因此我知道s2绑定到表达式s1 + s1,但是在s2被分配的时候评估过,还是懒惰,并在调用s2 += "Test";时被评估?并且s2也会为内存暂存一个字符串?什么时候评估了右值?

#include <iostream> 
#include <string> 

int main() 
{ 
    std::string s1 = "Test"; 
    std::string&& s2 = s1 + s1; 
    s2 += "Test"; 
    std::cout << s2 << '\n'; 
} 

回答

16

s2结合到表达s1 + s1,但是这是在时刻s2评价被分配

是。

而且s2会为内存暂存一个字符串吗?

准确地说,s2绑定到临时std::string

s1 + s1将产生一个临时std::string,这将被绑定到参考s2(及其寿命延长到参考的寿命)。然后s2 += "Test";,在s2上执行operator+=(),即临时std::string

+0

感谢您的快速回复。看起来,如果's2'只是另一个'std :: string',结果将是相同的,但是结果二进制文件会有什么不同? –

+0

@BradyDean是的结果是一样的。关于结果二进制文件很难说;无论如何,我试过[这里](https://gcc.godbolt.org/),它给了同样的程序集。 – songyuanyao

+0

请注意,这种情况在C++ 17中发生了变化,在这种情况下,可观察到的差异为零。 – Yakk

2

表达式总是在程序到达它们的时候进行评估。表达式的结果总是一个值(或无效)。

值有一个类型,表达式有一个值类别,它可以组合使用任何特定用途的过载集合的重载。

在你的情况下,string operator+(...)产生一个字符串值,带有类别pr值(这是一种右值)。然后它立即绑定到一个字符串& &,所以它的生命周期延伸到参考的寿命。

如果您改为将其分配给一个纯字符串,那么string& string::operator=(string&&)将被选择为该运算符的任何其他重载。请注意,由于C++ 11允许编译器(并且需要C++ 17)直接在目标对象内实现该值。此过程称为复制/移动省略或(N)RVO,用于(命名)返回值优化。

+0

@Yakk哪些东西特别重要?据我所知,唯一的变化就是移动的构造被忽略了,这与C++ 14的字符串 – Caleth

+1

没有明显的不同。对不起,我发誓我看到了“物体”这个词,它不应该是这个词,但我现在没有看到它,所以我一定是错的。 – Yakk

相关问题