为什么不为匿名对象调用析构函数?

Why destructor is not getting called for anonymous objects?

在工作时,我遇到了一段 strange/confusing 我觉得与 anonymous object 生命周期相关的代码概念。以下是示例代码:

#include<iostream>
#include<string>

class A {
private:
    int i;
    std::string s;
public:
    A(int ii, std::string ss = "Hello") { i = ii; s = ss; }
    void Display() { std::cout<<i<<"\n"; }
    ~A() { std::cout<<"A::~A()"<<"\n";}
};

void function()
{
    A a = 1;
    //A a = A(1);
    a.Display();
}

int main()
{
    function();
    return 0;
}

Output1(If A a = 1) in VS2010

 1
  A::~A()

Output2(If A a = A(1)) in VS2010

A::~A()
1
A::~A()

output2 完全有意义,因为 析构函数 被调用两次(包括匿名)对象。

但是 output1 让我感到困惑并且无法理解为什么 destructor 被调用一次(不是匿名的)对象。

A a = 1;

上一行将调用 class A 的复制构造函数 (A(const A& rhs)),编译器应使用参数 1 为此创建匿名对象。如果是这种情况,析构函数应该被调用两次。

有人可以向我解释一下这种行为吗?。可能是我遗漏了一些明显的东西。

您的编译器正在省略 A a = 1 的副本,但不会删除 A a = A(1); 的副本,gcc 在这两种情况下都能够 elide 副本,可以使用 [=12 进行测试=].

A a = A(1); 等同于 A a = 1;。但是,在这两种情况下,都可能出现copy elisionA(1)实际上是直接构造成a,而不是单独构造然后复制或移动。

由编译器决定是否在其允许的任何情况下执行复制省略(如上文所述link)。