我理解如何移动对象,例如:
int a(5), b(6);
int c(std::move(a));// move constructor
c = std::move(b);// move assignement
我理解自定义移动构造函数的常见实现,该构造函数获取动态指针的所有权并将移动的值设置为nullptr。
但我还没有找到任何关于自己移动动态分配指针的信息。我需要确认以下代码是合法的:
int *p(new int(42));
int val(std::move(*p));
delete p;// i think this is no longer necessary. is it ?
是否允许移动动态指针?
答案 0 :(得分:2)
std::move
不动任何东西。它只是将一个l值引用转换为r值引用。
在你给出的例子中,指针p
没有移动到任何地方。
顺便说一句。请不要处理原始指针 - 改为使用std::unique_ptr
。
这为int分配内存,将int初始化为值42并将该内存的地址存储在p中。
int *p(new int(42));
这会将p
指向的int强制转换为int&&
,然后从该r值引用构造int val
。由于int是一个整数类型,因此r值(即移动)的构造等同于副本(这是标准中规定的)
int val(std::move(*p));
是的,这仍然是必要的。
delete p;// i think this is no longer necessary. is it ?
答案 1 :(得分:1)
在第二个示例中,您的代码基本上将一个整数的值复制到另一个整数。你没有移动指针,你正在移动指针指向的整数。
int a = 42;
int b = std::move(a);
std::cout << a << " : " << b << std::endl; // prints 42 : 42
移动整数就是复制它们。
即使您移动了指针,也会复制指针的值:
int* a = new int{42};
int* b = std::move(a);
std::cout << *a << " : " << *b << std::endl; // prints 42 : 42
std::cout << std::boolalpha << (a == b) << std::endl; // prints true
因此,移动原始指针也会复制它们。
您仍然需要删除p
指针。
对于每一个新的,都有删除。
如果您不想自己删除它,请考虑std::unique_ptr
,它知道移动语义。
内置类型如原始指针,int,浮点数不知道移动语义,移动它们只会复制它们。
答案 2 :(得分:0)
在您的示例中,移动语义的使用是微不足道的,因为您只使用原始类型和原始指针。 std::move
实际上什么也没做。
当对象属于支持移动操作的类(移动构造函数,移动赋值等等),或者与其他类/函数交互时,移动语义会产生差异。
简单地说,从一个对象移动(不是std::move
本身的结果,但是后续调用的结果)后,该对象仍处于活动状态并处于有效状态,尽管它已被剥夺任何托管内容。物体的破坏仍有待完成,它仍然是一个活物。
请注意,您很少看到带有原始指针的移动语义。通常使用自动存储对象或智能指针来查看它。而这仅仅是因为移动语义与之相配的场景。