【问题标题】:Is this the right way to use std::move?这是使用 std::move 的正确方法吗?
【发布时间】:2021-01-05 03:28:28
【问题描述】:

我正在尝试在下面的代码 sn-p 中保存 char[10] 的副本,只是想知道这是否是使用 std::move 的正确方法,这实际上会保存 char[10] 的副本Struct2 对象正在构建中。

#include <string>
#include <iostream>
#include <cstring>
#include <memory>
using namespace std;


struct Struct1 {
    int a;
    string b;
    char c[10];
};

struct Struct2 {
    const Struct1 struct1;
    int d;
    string e;
};

int main() {
    int a = 10;
    auto b = "b";
    char c[10] = "12345";
    Struct1 struct1{a, b};
    strcpy(struct1.c, c);
    Struct2 str2{std::move(struct1), 10, "e"}; //<-- no copy of struct1.c, right?
    cout << str2.struct1.c << endl;
}

如果我不想复制char[10] 两次(Struct1 将不会被用作Struct2 的字段以外的其他字段),那么在构造 Struct2 中是否有更好的语法?

【问题讨论】:

    标签: c++ c++11 move-semantics


    【解决方案1】:

    C 数组对于移动和复制具有相同的语义。换句话说,C 数组的复制和移动完全相同。

    优势在于std::string,例如会员Struct1::b.

    是的,这是std:: move 的正确语法/用法。

    【讨论】:

    • 这是否意味着它总是将stealmovecopy 转移到一个新地址?
    • 不!这意味着它不会偷窃。它会复制内容。
    • 所以如果我想避免复制,我真的应该将 struct1 包装在 shared_ptr 中吗?
    • 我已经为你添加了一个例子作为另一个答案
    • @tesla1060 move 是一种转让所有权的工具。它与仅针对类类型的副本具有任何有意义的不同。原始类型的对象没有所有权,数组没有所有权(而数组的元素可能有)。
    【解决方案2】:

    如果您使用调试器查看变量,您会发现唯一移动的实体是非 POD(“普通旧数据”)字符串 b。搬家前你有:

    搬家后你有:

    你会看到'b'字符串data已经被复制到一个新的内存位置并且旧的被擦除但是它仍然在0x00edfe40有它的原始缓冲区

    正如其他人所说,std::move 更关心所有权转移,确保不保留副本,而不是避免复制内存本身。

    【讨论】:

      【解决方案3】:

      这里是一个建议,而不是污染我之前的答案:

      如果你想使用 unique_ptr,试试这样的方法。不幸的是,make_unique 不能很好地与初始化列表配合使用,因此您必须定义一个非默认构造函数(除非有人知道解决这个问题的方法?)。

      class Struct1
      {
      public:
          int a;
          string b;
          char c[10];
      
          Struct1::Struct1(int _a, string const&& _b, char const* _c) : a(_a), b(_b)
          {
              strcpy_s(c, 10, _c);
          }
      };
      
      using Struct1_unique = std::unique_ptr<Struct1>;
      
      typedef struct 
      {
          Struct1_unique pStruc1;
      //  const Struct1 struct1;
          int d;
          string e;
      }
      tsStruct2;
      
      
      int main() {
          int a = 10;
          auto b = "b";
          char c[10] = "12345";
          //Struct1 struct1{ a, b };
          Struct1_unique pStruc1 = std::make_unique<Struct1>(a, b, c);
          //strcpy_s(pStruc1->c, 10, c);
          tsStruct2 str2{ std::move(pStruc1), 10, "e" };
          cout << str2.pStruc1->c << endl;
          str2.pStruc1.reset();
      }
      

      所以,在搬家之前,你有:

      之后:

      您可以看到对象的所有权已经转移(pStruc1 现在“空”)而没有进行任何复制;指向对象的指针和其中的字符串数据没有改变。最后的reset 释放对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-18
        • 1970-01-01
        • 2012-06-28
        • 2012-05-11
        • 2018-12-31
        • 2021-04-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多