c++ - 我是否应该将使用 push_back 的代码更改为使用 std::move?

标签 c++ stl stdmove

我刚刚阅读了有关右值引用的内容,下面是我所指的代码

vector<string> v;
string s = "hello";   

v.push_back(s); 
cout << s << endl;
cout << v[0] << endl;
return 0

我的问题是,直到现在,每当我看到对象(或字符串)的 vector 时,我大多看到插入是像上面那样完成的。相反,如果我执行了 v.push_back(std::move(s)) 那么我就不会不必要地创建重复对象。

这应该是将对象添加到 STL 的正确方法吗?我们只关心容器中的数据而不是其他变量。

最佳答案

鉴于我收到的评论,我决定采用不同的方法来回答这个问题。这是一个使用各种方法将对象添加到 vector 的程序。该程序准确打印出在所有情况下调用了哪些复制构造函数、移动构造函数、复制运算符、移动运算符和析构函数。

该程序使用了不起的 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()

我会说这个程序的输出完全符合我的预期,并且输出(据我所知)与我之前在这里得到的答案一致。


<子> Why I use ::std:: instead of std::

关于c++ - 我是否应该将使用 push_back 的代码更改为使用 std::move?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54390665/

相关文章:

c++ - std::move(const shared_ptr 引用) 是什么意思?

c++ - OpenCV 中 VideoCapture 对象的状态

c++ - 如何找到auto_ptr的地址

c++ - 如何在子类控件中使用快捷键表?

c++ - 如何为 std::transform 创建正确的接口(interface)

c++ - 按值返回的函数的 return 语句中的初始化

c++ - C++ 类是否解决了函数覆盖问题?

c++ vector 迭代器到函数模板

c++ - 在 C++ 中获取 URL 的最后 N 段

c++ - std::vector 的前地址是否移动不变?