“new Foo()”和“&Foo()”作为参数的区别

Posted

技术标签:

【中文标题】“new Foo()”和“&Foo()”作为参数的区别【英文标题】:Difference between “new Foo()” and “&Foo()” as parameters 【发布时间】:2019-05-27 11:24:02 【问题描述】:

我对关键字new& 在特定上下文中的区别有一些疑问。

假设这是我的代码:

struct Base ;
struct Foo : Base ;
struct Storage

    void save(Base * object) 
    Base * content;
;

int main()

    Storage s1, s2;
    s1.save(new Foo());
    s2.save(&Foo());

main 执行后,s1 将持有一个指向Foo 类型对象的指针。然而s2 将持有一个指向Base 类型对象的指针。 s2.content 只会指向 Foo 类型的对象,直到 save 方法完成执行。

如有错误请指正:

据我了解new Foo() 创建了一个指向Foo 类型的新对象的指针。另一方面,&Foo() 首先创建一个 Foo 类型的新对象,然后指向它。

那么new Foo()&Foo() 之间到底有什么区别呢?显然,两者都为您提供了指向 Foo 类型的现有对象的指针。

为什么new Foo()创建的对象在执行save方法后仍然存在,而&Foo()创建的对象却没有?

可能是&Foo() 创建了一个临时对象,执行保存后该对象将不复存在?如果是,我怎样才能延长通过&Foo() 创建的对象的生命周期以使其存活(至少)直到s2 被销毁?

编辑 1: 非常感谢您的快速回答!我只是在使用 Visual Studio,所以 &Foo() 编译可能是一些微软特有的东西......

【问题讨论】:

不能延长&Foo()的寿命 最明显的区别是一个编译而另一个不编译...wandbox.org/permlink/qWn4eVLP3HWhIeGt "我怎样才能延长通过 "&Foo()" 创建的对象的寿命...这就是 new Foo() 的用途。 "然而s2 将持有一个指向Base 类型对象的指针。" - 是什么让你这么认为? 如果您将警告级别提高到至少 4,您会收到“警告 C4238:使用非标准扩展:类右值用作左值”。 【参考方案1】:

那么“new Foo()”和“&Foo()”到底有什么区别呢? 显然,两者都给你一个指向 Foo 类型的现有对象的指针。

为什么“new Foo()”创建的对象在执行后仍然存在 保存方法,而通过“&Foo()”创建的对象没有?


new Foo()

new Foo();

这会创建一个动态分配 Foo 对象并返回一个指向该对象的指针。动态分配的对象将一直存在,直到它们被程序员明确删除:

Foo* foo = new Foo();
delete foo; // delete the object.

&Foo()

Foo();

这会使用 automatic-storage 创建一个Foo 对象。这意味着它的生命周期,当对象被删除时,由对象所在的范围决定:


  Foo foo; // foo lives in automatic storage.
 // end of scope, foo dies

在您的情况下,您正在创建一个新的Foo 对象,并且将此匿名对象的地址传递给Storage::save。该对象将在完整表达式结束时被销毁。这基本上意味着在s2.save() 返回后,您的对象将被销毁,并且在s2 中指向它的指针将悬空,并且取消引用它将是未定义的行为。


如果是,如何延长通过“&Foo()”创建的对象的寿命 让它存活(至少)直到 s2 被破坏?

你不能。您可能需要一个智能指针,例如std::unique_ptr


请注意,获取临时地址是非标准的,因此此代码一开始就不合规。您的编译器可能正在使用扩展来允许它。 MSVC 以允许这样做而闻名。

【讨论】:

【参考方案2】:

表达式 Foo() 创建一个新的 temporary 对象,并且在该临时对象上使用地址运算符 & 将导致编译器错误,因为它不允许获取像这样的临时对象(Foo()rvalue 并且不能在这些对象上使用 address-of 运算符)。

使用new Foo 创建一个 临时对象,结果是指向该对象的指针。这个对象的生命周期是直到你明确地delete 它。如果你不delete它,那么你就会有内存泄漏。

【讨论】:

VS 出于某种原因允许绑定 @LightnessRacesinOrbit /W4 会发出警告。不幸的是,/permissive- 并没有使它成为一个硬错误。 @LightnessRacesinOrbit 不幸的是,这是一个非常非标准的 MSVC++ 扩展。

以上是关于“new Foo()”和“&Foo()”作为参数的区别的主要内容,如果未能解决你的问题,请参考以下文章

“#if Foo - 0 == 0”和“#if defined(Foo) && Foo == 0”有啥区别?

auto foo = ref new Foo();啥是“参考”?

在 PHP 中,当 $foo = new Foo() 时,从技术上讲,$foo 是一个对象,还是 $foo 一个引用?

什么是“x && foo()”?

JS 操作符优先级及new

定义仅在某个模块/类中可见的方法