这是使用 std::move 的正确方法吗?

Is this the right way to use std::move?

我正在尝试在下面的代码片段中保存 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 数组的复制和移动做完全相同的事情。

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

是的,这是 std:: move 的正确 syntax/usage。

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

搬家之后你有:

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

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

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

如果您想使用 unique_ptr,请尝试这样的操作。不幸的是 make_unique 不能很好地使用初始化列表,所以你必须定义一个 non-default 构造函数(除非有人知道解决这个问题的方法吗?)。

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 释放对象。