【问题标题】:c++ vector - what's the difference between push_back(*new obj()) and push_back(obj())? [closed]c++ vector - push_back(*new obj()) 和 push_back(obj()) 有什么区别? [关闭]
【发布时间】:2014-02-16 08:59:26
【问题描述】:

我目前遇到的问题与以下相关:

vector<myObj> myVector;

第一季度。请告诉我以下两行之间的区别:

a) myVector.push_back(*new myObj());
b) myVector.push_back(myObj());

注意:我意识到 a) 行是不好的做法,因为它在将 myObj 的内容复制到向量之前动态分配它会导致内存泄漏,因此无法释放...

然而,我假设这两行应该导致向量包含完全相同的内容,尽管这个假设似乎是不正确的。我目前正在开发的软件使用 a) 行运行良好(我知道,我知道这会导致泄漏,请暂时忽略这一点)但在 b) 行出现各种不同的 exc_bad_access 错误而崩溃。

第二季度。谁能解释为什么会这样?

编辑:发布此内容时,我最初认为我的问题必须与结果矢量内容的某些差异有关,但我的问题实际上与履行“三法则”http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) 有关 感谢@WhozCraig、@juanchopanza 和@Alex Antonov 的帮助!

【问题讨论】:

  • *new myObj() 我向您介绍内存泄漏运算符。
  • 请显示myObj的定义。
  • 如果它不与 (a) 一起崩溃,但与 (b) 一起崩溃,则在 myObj 的某处,您可能无法满足 Rule of Three。我几乎敢打赌。
  • 抱歉等待@WhozCraig!会尽快解决,如果有帮助,请告诉您!非常感谢您的建议!

标签: c++ vector memory-management heap-memory push-back


【解决方案1】:

有什么区别...

不同之处在于 a) 行会导致内存泄漏,而 b) 行不会。这是因为 a) 中动态分配的对象立即被丢弃,并且没有句柄可以在其上调用delete。向量保存并拥有它的元素,在这种情况下,这些元素是您推回其中的内容的副本。

我目前正在开发的软件使用 a) 行运行良好,但在 b) 行出现各种不同的 exc_bad_access 错误而崩溃。

它可能看起来运行良好,但它有资源泄漏。所以不管怎么想都不好。如果您对 b) 行有疑问,可能是因为 myObj 管理资源而不遵循 rule of three。 b) 行对于设计良好的类应该可以正常工作。

【讨论】:

  • @RohitChatterjee 他声称知道它,但从文本和“有效”的声明来看,他似乎并不真正知道它。此外,a) 不可能“工作”,它可能只是看起来这样做。
  • @mindTree 然而你问这两行之间的区别。所以我告诉你区别。如果我添加一个“你已经知道...”会更好吗?
  • @mindTree 没有区别,除了内存泄漏(除非你为myObj 重载了new)。这就是我的回答告诉你的。你有错误的代码,未定义的行为,并且会以各种奇怪的方式表现出来)
  • @mindTree juan 和我提供的链接都不起作用吗?想想(b)做了什么,但用(a)做了什么。即创建了两个对象(一个在new 表达式中,一个在vector by-copy 中),但由于泄漏,只触发了一个析构函数。您可能会得出结论,当两个析构函数都开火时,就会发生混乱。因此,我向您提交您在myObj 的复制构造函数中的浅复制动态分配,并在此过程中打破了三法则。 阅读那篇文章。我们不是魔术师,没有按要求提供myObj 的来源,猜测就是你得到的。
  • 现在他投了反对票……太棒了……
【解决方案2】:

A1:不同之处在于(a)在堆上创建一个对象,然后取消引用它,而(b)创建一个堆栈对象。

A2:由于您还需要删除堆分配的对象,您会遇到内存泄漏。 std::vector 不会为您执行此操作,因为它无法知道传递的对象是在堆上分配还是在堆栈上分配。

将对象插入向量时,将被复制。如果要保留堆分配的对象,则需要这样定义:

std::vector<*myObj> myVector;

【讨论】:

  • 感谢您的回复 qstebom,我知道这一点。但是,我主要关心的是生成的矢量内容有什么不同?
  • std::vector 看起来像错字
  • 另外,使用“动态与自动分配”而不是“堆栈与堆”。 “堆栈”和“堆”是实现细节,在描述抽象行为时无关紧要。它们甚至可能不存在。
  • 谢谢@H2CO3!从现在开始,我将编辑问题并牢记这一点!
  • myObj 不是我的错字。 :)
【解决方案3】:

在 a) 行中,您正在创建 2 个对象,并且您有以下方法调用:
1) 第一个对象的默认构造函数
2) 第二个对象的复制构造函数

在 b) 行中,您还创建了 2 个对象,但您有以下方法调用:
1) 第一个对象的默认构造函数
2) 第二个对象的复制构造函数
3) 第一个对象的析构函数

很明显,a) 行有效,因为没有调用析构函数。这意味着很可能在 b) 行中,您正在析构函数中释放/释放某些资源(例如动态分配的内存),然后尝试通过第二个对象访问该资源。在这种情况下,您需要正确实现复制构造函数。例如。您需要在复制构造函数中分配新的内存/对象,而不是简单地复制指向内存/对象的指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    相关资源
    最近更新 更多