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

时间:2015-06-26 05:00:40

标签: c++ oop c++11 copy-constructor anonymous

在工作的时候,我遇到了一段奇怪/令人困惑的代码,我觉得这些代码与匿名 对象生命周期概念有关。下面是代码示例:

#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;
}

VS2010中的输出1(如果A a = 1)

 1
  A::~A()

VS2010中的输出2(如果A a = A(1))

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

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

然而 output1 让我感到困惑,无法理解为什么析构函数被调用一次(不是匿名)对象。

A a = 1;

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

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

2 个答案:

答案 0 :(得分:8)

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

由编译器决定是否在其允许的任何场景中执行复制省略(如上面的链接所述)。

答案 1 :(得分:3)

您的编译器正在删除Public Sub SaveRaidDetails() lblStatus.Text = "" Dim dt2 As DataTable = CType(ViewState("dt1"), DataTable) Dim er As Boolean = False Dim dtRaidDate As Date If dt2.Rows.Count > 0 Then Try dtRaidDate = Convert.ToDateTime(txtRaidDate.Text) Catch ex As Exception er = True End Try If er = False Then lblDateEr.Visible = False Dim intDisID, intMktSeq, intAgID As Integer Dim dblFine As Double If ddlDistributor.SelectedValue = "" Then intDisID = 0 Else intDisID = ddlDistributor.SelectedValue End If If ddlMarkets.SelectedValue = "" Then intMktSeq = 0 Else intMktSeq = ddlMarkets.SelectedValue End If If ddlAgency.SelectedValue = "" Then intAgID = 0 Else intAgID = ddlAgency.SelectedValue End If If txtFine.Text = "" Then dblFine = 0 Else dblFine = Convert.ToDouble((txtFine.Text)) End If Dim intUserSeq As Integer = Convert.ToInt32(Session("UserSeq")) Dim ret As Boolean Dim rd1 As New RIMS_DATA.Raids ret = rd1.AddRaid(dtRaidDate, txtCo.Text, txtCa.Text, intDisID, Convert.ToInt32(ddlRegion.SelectedValue), intAgID, intMktSeq, txtTrader.Text, txtTraderAdd.Text, dblFine, txtRemarks.Text, intUserSeq) If ret = True Then Dim intRaidID As Integer = rd1.ReadLastRaid() Dim dtBatchDt As Date For Each dr As DataRow In dt2.Rows Try dtBatchDt = Convert.ToDateTime(dr("BDt")) Catch ex As Exception dtBatchDt = Convert.ToDateTime("01/01/2000") End Try ret = rd1.AddRaid2(intRaidID, Convert.ToInt32(dr("BID")), Convert.ToInt32(dr("Qty")), dr("BCd"), dtBatchDt) Next ClearForm(1) lblStatus.Text = "Record inserted successfully !" lblDateEr.Visible = True End If End If End If Else lblStatus.Text = "Please enter the raid details !" End If 的副本,但不会删除A a = 1的副本,gcc在这两种情况下都可以elide副本,可以使用A a = A(1);进行测试