2

给定以下代码:

#include <iostream>

struct implicit_t
{
    implicit_t(int x) :
        x_m(x)
    {
        std::cout << "ctor" << std::endl;
    }

    ~implicit_t()
    {
        std::cout << "dtor" << std::endl;
    }

    int x_m;
};

std::ostream& operator<<(std::ostream& s, const implicit_t& x)
{
    return s << x.x_m;
}

const implicit_t& f(const implicit_t& x)
{
    return x;
}

int main()
{
    std::cout << f(42) << std::endl;

    return 0;
}

我得到以下输出:

ctor
42
dtor

虽然我知道这是正确的,但我不确定为什么。有没有 stdc++ 知识的人可以向我解释?

4

4 回答 4

13

临时对象被销毁作为评估完整表达式(1.9)的最后一步,该完整表达式(在词法上)包含它们被创建的点。[12.2/3]

于 2009-12-03T01:41:08.563 回答
6

12.2 临时对象,第 3 节:“临时对象被销毁,作为评估完整表达式 (1.9) 的最后一步,该完整表达式 (从词法上) 包含它们被创建的点。”

1.9 程序执行,第 12 条:“完整表达式是不是另一个表达式的子表达式的表达式。”

于 2009-12-03T01:42:58.707 回答
1

由于有一个构造函数可以接受传递给 F() 函数的参数,因此编译器会在将参数放入堆栈之前动态创建对象。从下面的反汇编中可以看到。默认情况下,文字数字被视为整数,因此可以接受转换。

001115C5  call        implicit_t::implicit_t (11112Ch) 
001115CA  mov         dword ptr [ebp-4],0 
001115D1  mov         esi,esp 
001115D3  mov         eax,dword ptr [__imp_std::endl (11A308h)] 
001115D8  push        eax  
001115D9  lea         ecx,[ebp-0D4h] 
001115DF  push        ecx  
001115E0  call        f (111113h) 

您的临时对象会一直挂起,直到表达式被完全评估。如果您向您的函数添加另一个调用,这可以更加明显。

int main()
{
    std::cout << f(42) << std::endl;

    std::cout <<f(80) << std::endl;

    return 0;
}

其输出为

ctor
42
dtor
ctor
80
dtor
于 2009-12-03T01:43:00.017 回答
-4

f(42)implicit_t隐式构造一个未命名的。它在其包含范围内存在,就像任何auto变量一样。自然地,d'tor 被召唤return 0;main()

于 2009-12-03T01:40:26.310 回答