在 C++11 中,局部变量的最后一次出现是否被视为右值?

Is the last appearance of a local variable treated as an rvalue in C++11?

局部变量在其范围内的最后一次出现是否被视为右值? (就像在 return 语句中一样。)例如。在下面的代码中,是将字符串移动到向量中还是应该明确写入 V.push_back(std::move(newitem))

struct Element
{
std::string s1 {};
std::string s2 {};
}

void f()
{

std::vector<Element> V;

 while (condition())
 {
     Element newitem { };

     newitem.s1 = "example1";
     newitem.s2 = "example2";

     V.push_back(newitem);
 };
};

在您的示例中,newitem 是一个左值(它是一个命名对象),因此不会使用移动构造器。如果您提供右值,编译器将使用移动构造函数,如:

V.push_back(std::move(newitem))

其中 xvalue 传递给 push_back。所以是的,你应该明确地使用 std::move

不,它不会自己调用std::move。 您可以试试这个代码:

#include <iostream>
#include <string>
#include <vector>
struct Element
{
    std::string s1;
    std::string s2;
    Element() = default;
    Element(const Element&) = default;
    Element(Element&& other){
        other.s1 = s1;
        other.s2 = s2;
        s1 = "";
        s2 = "";
    }
    ~Element()
    {
        std::cout << s1 << " " << s2 << std::endl;
    }
};

void f()
{
    auto V = new std::vector<Element>{};  // deny destucting the vector
    V->reserve(10000); // deny reallocation
    size_t i{ 0 };
    while (i++<5)
    {
        Element newitem{};
        newitem.s1 = "example1";
        newitem.s2 = "example2";
        V->push_back(newitem);
    }
}
int main()
{
    f();
    std::getchar();
}

Live Demo

Result:

example1 example2

example1 example2

example1 example2

example1 example2

example1 example2

尝试使用 V->push_back(std::move(newitem)); 并查看差异。

P.S。上面的代码导致内存泄漏。它是故意这样做的,以防止调用析构函数。

newitem 有一个名字,所以只要你不使用 std::move 它将被视为左值。

有趣的是,使用 Visual studio 2013 和 /O2 构建此代码时,编译器并未优化任何调用。 (你会期望因为没有人在之后使用 newitem 编译器会将所有内容转换为就地构造)

性能方面,你也可以使用emplace_back:

V.emplace_back(std::string("hello"),std::string("world"));

std::string 包装器不是多余的)