【问题标题】:C++ Difference between *new and new [duplicate]C ++ *new和new之间的区别[重复]
【发布时间】:2013-04-20 14:56:48
【问题描述】:

这个问题可能是重复的。我一直在网上到处寻找以解决这个问题,但我找不到任何东西。 'new' 和 '*new' 有什么区别?:

int main()
{
    class Cat
    {
        //Code
    }

    new Cat();
    *new Cat();

    return 0;
}

【问题讨论】:

  • 我很好奇,你在哪里看到的?
  • @AlokSave 不,它不是那个的副本。我还在学习 C++,我什至不知道内存泄漏是什么
  • @JBentley 我来自 java。我只想能够将新对象放入数组/列表中。在java中,你做“object[5] = new object();”
  • @Harry 我的意思是你在某处看到的一些代码中看到了*new 的例子吗?
  • @JBentley 不。我的意思是我没有在 c++ 中看到过这个,我只在 java 中看到过。我试图弄清楚如何制作一个新对象并将其存储在内存中,就像你在 java 中所做的那样。

标签: c++ object pointers


【解决方案1】:

这不是两个独立的东西。没有new*new。第二种是简单地将一元 * 应用于 new Cat() 的结果。

new Cat() 是一个新表达式。它动态分配和初始化Cat 对象并计算出指向该对象的指针。如果随后将一元 * 应用于该指针,则取消引用它以获取 Cat 对象。

通常没有很好的理由立即将一元 * 应用于 new-expression。原因是您立即跟随指针并且没有将指针存储在任何地方。考虑一下你是否这样做过:

Cat c = *new Cat();

这会导致您无法恢复的内存泄漏。 Cat 对象被动态分配,然后复制到c。动态分配的Cat 现在徘徊,你没有指向它的指针,你可以通过它delete 对象。这很糟糕。

Cat& c = *new Cat();

这样好一点,因为至少现在c 只是对动态分配对象的引用。您可以随时使用delete &c; 来销毁该对象。但是,它掩盖了Cat 是动态分配的事实。如果我正在阅读这段代码,我不会期望 c 指的是动态分配的对象。

您必须记住销毁动态分配的对象。取消对 new-expression 的结果的引用会使实现这一目标变得更加困难,因此请避免这样做。

【讨论】:

    【解决方案2】:

    这个表达式:

    new Cat();
    

    动态创建Cat 类型的对象,您忽略返回的指针(不存储它,不取消引用,什么都没有)。这个表达式:

    *new Cat();
    

    和上面的一样,除了你还取消引用new返回的指针。但是取消引用指针本身是一个没有副作用的操作。

    因此,具体而言,这两种表达方式的效果是相同的。重要的一点是,您正在泄漏内存两次,因为丢失了一次并且仅引用了您动态创建的对象。

    请记住,使用new 创建的每个对象都必须通过对delete 的相应调用来销毁。例如,如果您以这种方式存储返回的指针:

    Cat* pCat = new Cat();
    

    这将允许您稍后再做:

    delete pCat;
    

    并避免内存泄漏。另外,这个:

    Cat& cat = *new Cat();
    

    稍后允许您这样做:

    delete &cat;
    

    并避免再次发生内存泄漏。但是请注意,这不是一个选项:

    Cat cat = *new Cat();
    

    以上内容仍然会给您带来内存泄漏。原因是它会将通过取消引用new 返回的指针获得的对象复制cat。换句话说,cat 将是与new 表达式创建的对象不同的对象(尽管相同)。

    另一方面,new 表达式创建的对象将丢失 - 再次导致内存泄漏。

    在现代 C++ 中,建议通过调用 newdelete 来避免手动内存管理;相反,请考虑使用智能指针(取决于您需要的所有权策略)。例如:

    #include <memory>
    
    // ...
    
    std::shared_ptr<Cat> pCat = std::make_shared<Cat>();
    

    当指向对象的最后一个智能指针被销毁时,智能指针会自动销毁被引用的对象。

    【讨论】:

    • 你怎么知道他在泄露内存?我经常使用第一种形式而不会泄漏内存,至少在特定类型的应用程序中是这样。这一切都取决于Cat 的构造函数做了什么。鉴于在许多应用程序中,对象将被对象中的delete this; 删除,作为对某些外部事件的反应,似乎没有任何理由对运算符 new 的返回值做任何事情。 (当然,构造函数已经处理了所需事件的注册。)这似乎是使用new 时最常见的情况。
    • @JamesKanze:我花了一段时间才明白你的意思,主要是因为你似乎对 OP 的问题做了很多非假设。 IMO 从文本中假设这里没有发生类似的事情似乎是合理的。一个完整的程序有一个常规的类,并且OP正在询问new*new之间的区别,所以我发现他们不太可能弄清楚一些自注册,自删除和事件- 那里的聆听模式。
    • 您似乎在做出假设。自注册/自删除模式非常频繁,可能应该在缺乏额外信息的情况下进行假设。无论如何,仅将您从 new 获得的值分配给智能指针,而不提供任何其他信息,肯定会导致灾难。
    • @JamesKanze:顺便说一句,你为什么特别选择我的答案?这里的每个人都在提到内存泄漏——这是因为我们可以合理地假设我们所看到的就是 OP 所拥有的。具有简单本地类的简单程序,不进行事件注册和自删除。
    • 因为我先看到了。这些问题并不像大多数响应者认为的那样明显。 (但*new 版本几乎可以肯定是一个错误。除非他对参考做了什么。)
    【解决方案3】:

    对你有帮助吗:

    Cat *ptr = new Cat();
    Cat cat = *new Cat(); /* memory leak :( */
    

    【讨论】:

    • 这是有道理的。不过我没有使用变量。
    • 注意,后者将新的Cat复制到cat,然后泄漏new分配的内存。
    • @JerryCoffin 谢谢,我在回答中提到了
    • 当然,如果你动态分配类,它可能不支持复制,所以第二个版本不应该编译。
    • @JamesKanze 在 c++ 中总是有一个默认的 = 运算符和复制构造函数,它们已实现,因此它可以工作,但可能无法按预期工作。
    猜你喜欢
    • 1970-01-01
    • 2016-10-04
    • 2015-07-01
    • 2013-12-20
    • 2017-09-02
    • 2012-12-12
    • 2018-02-25
    • 2018-10-18
    • 2017-10-17
    相关资源
    最近更新 更多