【问题标题】:What is the difference between Rust's Drop and C++'s destructor?Rust Drop 和 C++ 析构函数有什么区别?
【发布时间】:2021-07-29 23:25:49
【问题描述】:

在阅读 Drop 特征时,我发现 Rust 的 drop 方法和 C++ 中的析构函数有很多相似之处。两者有什么区别?

【问题讨论】:

  • Rust 不是基于类的语言,而是基于特征的语言。 Drop 是一个可以实现也可以不实现的特征。在 C++ 中,每个类都有一个析构函数,无论你是否需要。
  • @nbro mem::forget 函数是安全的 Rust,但你不能无意中调用它
  • 我不会说没有区别,但区别可能微不足道。 The documentation for Drop 甚至称它为析构函数。您有更具体的问题吗?
  • 嗯,我上面提到的差异仍然很大,但这是由于语言的设计不同。
  • 我能想到的唯一真正的区别是 C++ 有关于涉及继承的析构函数的规则。由于 Rust 没有继承,这些规则并不真正适用于 Rust。

标签: c++ rust


【解决方案1】:

在实践中,没有明显的区别。两者都用于在适当的时候清理某个类型的资源。

无论Drop trait 的实现如何,资源都会被清理,不是吗?

是的。对于程序员没有的任何类型,编译器基本上会自动实现Drop。这种自动实现只是为每个成员变量依次调用drop

如果您分配 Rust 不知道的资源,例如直接从分配器分配内存,Rust 将不知道需要删除返回的值或如何删除。那是你直接实现Drop 的时候。

另见:

【讨论】:

  • drop()真的是用来清理资源的吗?无论 Drop trait 的实现如何,资源都会被清理,不是吗?
  • @ayushprashar:如果您进行系统调用来分配资源,例如分配内存,则不会为您清理。 rust 编译器甚至不知道如何清理它,它假设你想要清理它以及如何清理它是冒昧的。
  • @BenjaminLindley 我并不是要传达系统调用,而是要传达 Rust 管理法则中的一般对象声明。
  • @ayushprashar:默认情况下,在指针上调用Drop 会... 什么都没有。这就是为什么对于像Vec 这样分配内存并拥有它的类,存在手动的Drop 实现来释放内存。
  • @Shepmaster 下面是 Drop 的实现 Box: // FIXME: Do nothing, drop is currently performed by compiler.
【解决方案2】:

我所知道的唯一区别与 C++ 具有但 Rust 没有的特性有关。其他人在上面的 cmets 中提到了继承,但更简单的示例可能是具有多个构造函数的类型。在 Rust 中,根据我们所说的“构造函数”的含义,我们可以说每种类型都只有一个构造函数(命名类型并初始化其所有字段的语法)。但在 C++ 中,一个类型可以有多个构造函数,重要的是,一个构造函数可以委托 给另一个。这是一个简单的例子:

class foo {
public:
  // the inner constructor
  foo(bool throw_in_inner_ctor) {
    if (throw_in_inner_ctor) {
      throw runtime_error("throw in inner ctor");
    }
  }

  // the outer constructor, which delegates to the inner one
  foo(bool throw_in_inner_ctor, bool throw_in_outer_ctor)
      : foo(throw_in_inner_ctor) {
    if (throw_in_outer_ctor) {
      throw runtime_error("throw in outer ctor");
    }
  }

  // the destructor
  ~foo() {
    cout << "foo dtor\n";
  }
};

int main() {
  try {
    cout << "construct a foo that throws in its inner ctor\n";
    foo(true, false);
  } catch (runtime_error) {}
  try {
    cout << "construct a foo that throws in its outer ctor\n";
    foo(false, true);
  } catch (runtime_error) {}
}

打印出来:

construct a foo that throws in its inner ctor
construct a foo that throws in its outer ctor
foo dtor

我们在这里看到的是,当内部构造函数抛出时,foo 的析构函数不会被调用。但是当外部构造函数抛出时,它会抛出。规则是,如果 any 构造函数无异常返回,我们的foo 将被破坏,无论其他委托构造函数可能做什么。 Rust 没有与这条规则等效的规则,既因为 Rust 没有委托构造函数,又因为 Rust 中的构造函数(如果你想这样称呼它们)不能运行任意代码并且不会失败。

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 2021-06-01
    • 2023-03-18
    • 1970-01-01
    • 2013-05-30
    • 2010-09-25
    • 2010-11-07
    相关资源
    最近更新 更多