临时对象什么时候被销毁?

发布于 2024-08-22 09:22:14 字数 390 浏览 4 评论 0原文

以下代码打印 onetwoThree。所有 C++ 编译器都希望如此吗?

#include <iostream>

struct Foo
{
    const char* m_name;

    ~Foo() { std::cout << m_name << '\n'; }
};

int main()
{
    Foo foo{"three"};
    Foo{"one"};   // unnamed object
    std::cout << "two" << '\n';
}

The following code prints one,two, three. Is that desired and true for all C++ compilers?

#include <iostream>

struct Foo
{
    const char* m_name;

    ~Foo() { std::cout << m_name << '\n'; }
};

int main()
{
    Foo foo{"three"};
    Foo{"one"};   // unnamed object
    std::cout << "two" << '\n';
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

玉环 2024-08-29 09:22:14

临时变量一直存在到创建它的完整表达式的末尾。您的变量以分号结束。

这是在 [class.temporary] p4 中:

作为评估 full 的最后一步,临时对象将被销毁- 表达式(词汇上)包含它们创建的点。

您的行为是有保证的,但是,[class.temporary] 中列出的此规则有例外情况] p5、p6 和 p7

  1. 缩短数组初始值设定项中默认构造的临时对象的生命周期
  2. ,缩短构造函数的默认参数的生命周期,同时复制数组,
  3. 通过绑定对临时对象的引用来延长临时对象的生命周期
  4. 延长临时对象的生命周期 for-范围初始化器

A temporary variable lives until the end of the full expression it was created in. Yours ends at the semicolon.

This is in [class.temporary] p4:

Temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created.

Your behavior is guaranteed, however, the are exceptions to this rule listed in [class.temporary] p5, p6, and p7:

  1. shortening the lifetime of default-constructed temporary objects in initializers of arrays
  2. shortening the lifetime of default arguments to constructors while an array is copied
  3. extending the lifetime of temporary objects by binding a reference to them
  4. extending the lifetime of temporary objects in a for-range-initializer
哽咽笑 2024-08-29 09:22:14

管理临时对象生命周期的规则与范围概念无关。范围是名称的属性,而临时对象没有名称。换句话说,临时对象没有作用域。

大多数情况下,临时对象的生命周期在创建该对象的完整表达式结束时结束,这就是您在实验中观察到的情况。这是一般规则,但也有一些例外。主要的一点是,如果您立即附加对临时对象的引用,则该对象的生命周期将延长以匹配引用的生命周期。

const Foo &rfoo = Foo("one");

上述临时对象将与 rfoo 存在一样长。

The rules that govern the lifetimes of temporary objects have nothing to do with notion of scope. Scope is a property of a name, and temporary objects do not have names. In other words, temporary objects have no scope.

Most of the time the lifetime of a temporary object ends at the end of the full expression that created that object, which is what you observed in your experiment. This is the general rule that has some exceptions. The main one is that if you immediately attach a reference to your temporary object, the lifetime of the object will be extended to match the lifetime of the reference

const Foo &rfoo = Foo("one");

The above temporary will live as long as rfoo lives.

滥情稳全场 2024-08-29 09:22:14

像这样的临时对象的范围只有一行。想想看,行结束后你就无法再引用它了,那么为什么该对象会保留下来呢?

如果不是这种情况,编译器将无法优化函数调用中的临时对象。

The scope of a temporary object like that is just one line. Think about it, you can no longer reference it after the line ends, so why would the object remain around?

If this weren't the case, compilers wouldn't be able to optimize out temporary objects in function calls.

清醇 2024-08-29 09:22:14

是的,这是所希望的。

Foo foo("two") 创建一个普通对象,该对象将在作用域结束时被销毁。

Foo("one") 创建一个临时对象,该对象在指令结束时被销毁[1]。为什么?因为指令结束后您将无法访问它。

[1] 刻意简化:我应该说序列点

Yes, it is desired.

Foo foo("three") creates a normal object which will be destroyed when the scope ends.

Foo("one") creates a temporary object, which is destroyed at the end of the instruction[1]. Why? Because there is no way you can access it after the instruction has ended.

[1] Deliberate simplification: I should have said sequence point.

留蓝 2024-08-29 09:22:14

因为标准委员会犯了错误。它这样做是因为他们选择让它这样做。它被定义为这样做。它应该被视为一个匿名实例,其范围与已命名的实例相同。从实例化点到块的末尾。显然,他们认为唯一的用途是将临时对象传递到函数中,在函数调用结束时将其压入堆栈并从堆栈中弹出......

未命名的对象仍应压入堆栈并保留在堆栈上,直到块结束,从而在预期时将其从堆栈中弹出。在单个语句中构造和销毁对象是没有意义的。我希望看到一个实际有用的实例/案例。如果它在块的持续时间内没有保留在范围内,那么它肯定是一个错误,并且至少应该生成一个警告。

Because the standards committee goofed. It does it because they chose to make it do it. It's defined to do it this way. It should be considered an anonymous instance with scope the same as if it had been named. From the point of instantiation to the end of the block. Apparently they thought the only use was for passing temporaries into functions where it's pushed on the stack and popped off the stack at the end of a function call...

An unnamed object should still be pushed onto the stack and remain on the stack until the block ends, thus popping it off the stack when expected. Constructing and destructing an object during a single statement is pointless. I'd like to see a single instance/case where this is actually useful. If it doesn't stay in scope for the duration of the block it should most certainly be an error and should at minimum generate a warning.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文