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

C++11 是局部变量在C+中被视为右值的最后一次出现+;11?,c++11,move-semantics,C++11,Move Semantics,局部变量在其作用域中的最后一次出现是否被视为右值?(就像在返回语句中一样。)例如,在下面的代码中,字符串是移动到向量中还是V.push_back(std::move(newitem))应该被显式写入 struct Element { std::string s1 {}; std::string s2 {}; } void f() { std::vector<Element> V; while (condition()) { Element newitem { };

局部变量在其作用域中的最后一次出现是否被视为右值?(就像在返回语句中一样。)例如,在下面的代码中,字符串是移动到向量中还是
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);
 };
};
struct元素
{
std::字符串s1{};
std::字符串s2{};
}
void f()
{
std::向量V;
while(条件())
{
元素newitem{};
newitem.s1=“example1”;
newitem.s2=“example2”;
V.推回(新项目);
};
};

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

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();
}
#包括
#包括
#包括
结构元素
{
std::字符串s1;
std::字符串s2;
元素()=默认值;
元素(常量元素&)=默认值;
元素(元素和其他){
其他1.s1=s1;
其他2.s2=s2;
s1=“”;
s2=“”;
}
~Element()
{

std::cout
newitem
有一个名称,因此只要您不使用
std::move
它将被视为左值

有趣的是,在使用Visual studio 2013和
/O2
构建此代码时,编译器没有优化任何调用。(您可以预期,由于没有人使用
newitem
,因此编译器会将所有内容转换为就地构建)

就性能而言,您还可以使用
安置_back

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

(std::string
包装器不是redandant)

return大小写是特殊的,特别涉及到复制省略,而不是简单的移动语义(新对象直接在调用方空间中创建,而不是在本地构建
移动
-ed)。否则,范围中的最终外观没有什么特别之处。