在 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();
}
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
包装器不是多余的)
局部变量在其范围内的最后一次出现是否被视为右值? (就像在 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();
}
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
包装器不是多余的)