【问题标题】:Immutable classes and memory in C++C++ 中的不可变类和内存
【发布时间】:2011-05-17 00:35:32
【问题描述】:

因此,作为我正在从事的个人项目的一部分,我对 C++ 的了解比在学校时更深入。我是一名 Java 开发人员,所以要再次适应内存管理有点困难,现在我要不遗余力地编写某种方式的代码,我有一个关于不可变类的快速问题。

当我将它们视为一个概念时,我当然会将它们与 Java 中的字符串进行比较。但是现在我在 C++ 中,重新分配操作可能会造成内存泄漏(或者至少,我认为它可以)。所以现在如果我这样做:

  MyImmutableClass a ("blah");
  a = a.modifyInSomeWay();

其中 modifyInSomeWay 返回一个新的 MyImmutableClass 实例,我没有调用解构函数。我在这里遗漏了什么可以防止“a”的第一个分配留在内存中吗?

【问题讨论】:

  • 如果您将赋值视为类似 Java 的赋值,则需要 a 作为指针。这是赋值运算符。
  • 我同意@Greg 的观点,即不可变对象甚至不应该允许重新分配。但是要回答您的问题,这一切都归结为赋值运算符,以及它是如何为给定类重载的。请参阅copy-and-swap idiom 上的说明。

标签: c++ class memory memory-management immutability


【解决方案1】:

在您描述的情况下,MyImmutableClass赋值运算符 被调用以将赋值的右侧复制到左侧(覆盖左侧的任何内容)。如果你的类真的是不可变的,那么它甚至一个可访问的赋值运算符,你会得到一个编译错误。

如果你的对象是可变的,并且你确实有一个(正确的)赋值运算符,那么就不会有内存泄漏,因为左侧数据的析构函数将根据需要运行以释放内存.但是,对于某些类来说,编写正确的赋值运算符可能会很棘手。

这种直接分配给(用户定义的)对象的概念在 Java 中不存在,因为那里的一切都是引用。

【讨论】:

  • 啊,我现在明白了,自从我的 C 类课程以来已经有一段时间了,我忘记了将东西放在堆上和放在堆栈上的区别。如果我改用MyImmutableClass* a = new MyImmutableClass("blah");,并稍后尝试用返回指向新对象的指针的方法覆盖指针,这会在析构函数中触发相同的行为吗?
  • @monitor:不,这会像您最初预测的那样发生泄漏。您可以使用多种智能指针来获得更安全的语义,例如下面提到的shared_ptrFredOverflow。
【解决方案2】:

由于其值语义,在 Java 中很多地方都可以找到共享不可变值对象的风格在 C++ 中效果不佳。说“对象应该是不可变的,但赋值应该仍然有效”是矛盾的。您可以使用shared_ptr<your_immutable_type> 类型的变量,但这会使代码混乱,因此在实践中很少有人这样做。

【讨论】:

    猜你喜欢
    • 2011-02-02
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    相关资源
    最近更新 更多