参数“ new Foo()”和“&Foo()”之间的区别

时间:2018-12-30 15:15:38

标签: c++ reference parameter-passing new-operator

对于在特定情况下关键字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()编译可能是一些Microsoft特定的东西...

2 个答案:

答案 0 :(得分:22)

  

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

     

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


new Foo()

new Foo();

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

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

&Foo()

Foo();

这将使用自动存储创建一个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允许这样做。

答案 1 :(得分:3)

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

使用new Foo创建一个 non 临时对象,结果是指向该对象的指针。该对象的生命周期是您明确delete之前。而且,如果您不delete,则会发生内存泄漏。