我刚刚阅读了右值引用,下面是我要引用的代码
vector<string> v;
string s = "hello";
v.push_back(s);
cout << s << endl;
cout << v[0] << endl;
return 0
我的问题是,到现在为止,每当我看到对象(或字符串)的向量时,我通常都会看到插入像上面那样完成。相反,如果我做了v.push_back(std::move(s))
,那么我就不必创建重复的对象。
这应该是将对象添加到STL的正确方法,而我们关心的只是容器中的数据,而不是变量。
答案 0 :(得分:5)
鉴于收到的评论,我决定采用其他方法来解决此问题。这是一个使用各种方法将对象添加到矢量的程序。该程序精确地打印出在所有情况下都调用了哪些复制构造函数,移动构造函数,复制运算符,移动运算符和析构函数。
程序使用出色的fmt library。 fmt::print
完全按照您的想法去做。我也许应该使用::fmt
。请记住,从对象移开通常会使它处于未指定的状态(请注意,与 undefined 不同)。当然,对于您自己编写的类,您确切地知道它处于什么状态。但是对于标准库类或其他人编写的类,则不需要。显然,对于标准库类,可以保证如果您执行某些操作将状态设置为已知状态,则对象确实会变为该状态。
就个人而言,我将对象视为从对象移出后对其唯一有效的操作就是调用其析构函数。但是我可以看到您可能只是想以某种方式重复使用存储的情况。
这是程序:
#include <fmt/core.h> // fmt
#include <vector> // vector
#include <utility> // move
class TestClass {
public:
TestClass(int a, int b) {
fmt::print("TestClass{{{}, {}}}\n", a, b);
}
TestClass(TestClass const &) noexcept {
fmt::print("TestClass{{TestClass const &}}\n");
}
TestClass(TestClass &&) noexcept {
fmt::print("TestClass{{TestClass &&}}\n");
}
TestClass const &operator =(TestClass const &) noexcept {
fmt::print("=(TestClass const &)\n");
return *this;
}
TestClass const &operator =(TestClass &&) noexcept {
fmt::print("=(TestClass &&)\n");
return *this;
}
~TestClass() noexcept {
fmt::print("~TestClass()\n");
}
};
int main()
{
::std::vector<TestClass> v;
// Reserve necessary space so movements of vector elements doesn't clutter up
// the output.
v.reserve(6);
fmt::print("Constructing initial\n");
TestClass o{1, 2};
fmt::print("\bv.push_back(o)\n");
v.push_back(o);
fmt::print("\nv.push_back(::std::move(o))\n");
v.push_back(::std::move(o));
fmt::print("\nv.push_back(TestClass{{3, 4}})\n");
v.push_back(TestClass{3, 4});
fmt::print("\nv.emplace_back(5, 6)\n");
v.emplace_back(5, 6);
fmt::print("\nv.emplace_back(::std::move(o))\n");
v.emplace_back(::std::move(o));
fmt::print("\nv.emplace_back(TestClass{{5, 6}})\n");
v.emplace_back(TestClass{5, 6});
fmt::print("\nHere H\n");
}
这是程序的输出:
Constructing initial
TestClass{1, 2}
v.push_back(o)
TestClass{TestClass const &}
v.push_back(::std::move(o))
TestClass{TestClass &&}
v.push_back(TestClass{3, 4})
TestClass{3, 4}
TestClass{TestClass &&}
~TestClass()
v.emplace_back(5, 6)
TestClass{5, 6}
v.emplace_back(::std::move(o))
TestClass{TestClass &&}
v.emplace_back(TestClass{5, 6})
TestClass{5, 6}
TestClass{TestClass &&}
~TestClass()
Here H
~TestClass()
~TestClass()
~TestClass()
~TestClass()
~TestClass()
~TestClass()
~TestClass()
我要说的是,该程序的输出完全符合我的预期,并且该输出(AFAIK)与我之前在这里得到的答案一致。
答案 1 :(得分:0)
// emplace_back在适当的位置构造元素。
emplace_back("element");
// push_back将创建新对象,然后复制(或移动)其参数值。
push_back(explicitDataType{"element"});
因此,在这里您应该使用
emplace_back()
而不是std::move()
。