“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();啥是“参考”?