为什么不为匿名对象调用析构函数?
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 elision: A(1)
实际上是直接构造成a
,而不是单独构造然后复制或移动。
由编译器决定是否在其允许的任何情况下执行复制省略(如上文所述link)。
在工作时,我遇到了一段 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 elision: A(1)
实际上是直接构造成a
,而不是单独构造然后复制或移动。
由编译器决定是否在其允许的任何情况下执行复制省略(如上文所述link)。