Перейти к содержанию

Последнее обновление:2026-10-12

Сравнение деструкторов C++ и Rust

В Rust mem::forget используется для предотвращения разрушения объекта, пропуская очистку, чтобы освобождение ресурсов было передано другим механизмам.

Например:

let file = File::open("foo.txt").unwrap();
mem::forget(file);

А как предотвратить разрушение в C++? То есть как пропустить вызов деструктора?

В этом разделе приводятся три способа; полные примеры кода также размещены в 知识星球.

1. placement new

placement new позволяет нам вручную управлять конструированием и разрушением объекта. Если не вызывать деструктор объекта вручную, можно пропустить разрушение объекта и тем самым добиться эффекта, аналогичного mem::forget.

Например:

alignas(Foo) std::byte storage[sizeof(Foo)];  // 分配对齐的原始内存块
Foo* pfoo = new (storage) Foo();  // 在这块内存上构造Foo对象

В приведённом коде placement new создаёт объект pfoo, но мы не вызываем деструктор — так можно пропустить логику очистки объекта.

2. Пользовательский удалитель умного указателя

Другой способ реализовать подобную функциональность — пользовательский удалитель умного указателя, предотвращающий уничтожение объекта. Можно определить удалитель, который ничего не делает, и тем самым избежать вызова деструктора.

std::unique_ptr<Foo, NoOpDeleter> pfoo(new Foo(), NoOpDeleter{});

Используя пользовательский удалитель NoOpDeleter, мы можем помешать std::unique_ptr вызвать деструктор при выходе из области видимости и тем самым добиться эффекта, аналогичного mem::forget.

3.union

Способ с union довольно удивителен — знаете ли вы, каков его принцип? Давайте обсудим это в комментариях~

template <class T>
union Wrapper {
  T value;
  ~Wrapper() {}
};

struct Foo {
  ~Foo() { std::cout << "dtor foo\n"; }
};

Wrapper<Foo> f; 
// f.value.~Foo);  必须手动调用

Похожие темы

Комментарии