【问题标题】:Should i delete a moved from dynamic pointer我应该删除从动态指针移动的
【发布时间】:2016-07-07 03:56:56
【问题描述】:

我了解如何移动对象,例如:

int a(5), b(6);
int c(std::move(a)); // move constructor
c = std::move(b);    // move assignment

我了解自定义移动构造函数的常见实现(它获取动态指针的所有权并将移动的指针设置为nullptr。)

但我还没有找到任何关于移动动态分配的指针本身的信息。我需要确认以下代码是否合法:

int *p(new int(42));
int val(std::move(*p));
delete p; // I think this is no longer necessary. Is it?

那么,是否允许移动动态指针?

【问题讨论】:

  • 说得非常非常简单——普通指针是愚蠢的。它们没有或不需要移动语义,因为它们只是一个愚蠢的指针。他们从来没有真正“拥有”任何东西,他们不会自动释放任何东西,除了他们自己(即指针,而不是指向的东西)。你打电话给new。你要么必须打电话给delete,要么有一些东西可以打电话给delete,因为你拥有你分配的东西的所有权。这段代码都不做,所以它会泄漏。

标签: c++ pointers dynamic move


【解决方案1】:

std::move 不移动任何东西。它只是将左值引用转换为右值引用。

在您给出的示例中,指针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 ?

【讨论】:

  • 如果p在任何地方都没有moved,这是否意味着我不再需要deletep?请帮我理解,谢谢
  • 编辑:事实上,我有一个唯一的指针,我想知道我是否可以将它传递给这样的函数: foo(std::move(*(ptr.release())) )
  • 好的,我明白了。我应该始终将移动视为构造函数行为,而不是内存置换。
  • @Cevik - 正确。 std::move 是一个强制转换,它邀请代码在可能的情况下防止复制(即,您已经编写了一个移动构造函数或允许编译器为您编写一个)。它对整数值没有影响 - 只有对象。
【解决方案2】:

在您的第二个示例中,您的代码实质上是将一个整数的值复制到另一个。您不是在移动指针,而是在移动指针指向的整数。

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,它知道移动语义。

原始指针、整数、浮点数等内置类型不知道移动语义,移动它们只会简单地复制它们。

【讨论】:

    【解决方案3】:

    在您的示例中,移动语义的使用是微不足道的,因为您只使用原始类型和原始指针。 std::move 真的什么都没做。

    当您的对象属于支持移动操作(移动构造函数、移动赋值等)的类或与支持移动操作的其他类/函数交互时,移动语义会有所不同。

    通常,在您从一个对象移动之后(不是std::move 本身的结果,而是后续调用的结果),该对象仍然是活动的并且处于有效状态,尽管它已被剥夺任何托管内容。物体的分解还有待完成,它仍然是一个活的物体。

    请注意,您很少看到带有原始指针的移动语义。通常可以在自动存储对象或智能指针中看到它。这只是因为移动语义可以很好地发挥作用。

    【讨论】:

    • 这应该是公认的答案。原帖碰巧以原始整数为例,碰巧是个特例。关键是std::move传递给的函数是做什么的。
    猜你喜欢
    • 2011-10-04
    • 2016-09-02
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 2016-03-02
    • 2016-12-15
    相关资源
    最近更新 更多