这是使用 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
释放对象。
我正在尝试在下面的代码片段中保存 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
释放对象。