我试图在下面的代码片段中保存char[10]的副本,只是想知道这是否是使用std::move的正确方式,这实际上会在构建Struct2对象时保存char[10]的副本。
#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;
}此外,如果我不想复制Struct2两次(除了作为Struct2的字段之外,Struct1不会被用作字段),在构造Struct2中是否还有更好的语法?
发布于 2020-09-18 08:12:33
C数组对于移动和复制具有相同的语义。换句话说,C数组的复制和移动也会做同样的事情。
优势将在std::string上,例如成员Struct1::b上。
是的,这是std:: move的正确语法/用法。
发布于 2020-09-18 08:33:49
如果使用调试器查看变量,可以看到唯一移动的实体是非POD(“普通旧数据”)字符串b。在搬家之前:

在搬家之后:

您将看到'b‘字符串数据已被复制到一个新的内存位置,旧的内存位置被删除,但它在0x00edfe40处仍然有它的原始缓冲区。
正如其他人所说的,std::move更关心所有权的转移,确保拷贝不被保存,比避免复制内存本身更重要。
发布于 2020-09-18 09:04:51
以下是一个建议,而不是污染我先前的答案:
如果您想使用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释放对象。
https://stackoverflow.com/questions/63951549
复制相似问题