[英]Strange behavior in C++ constructor\destructor
我正在通過遞歸使用C ++類構造函數來打印“表格”。 在我決定“為什么不遞歸使用析構函數?”之前,一切似乎都是正常的。 當我還使用析構函數實現打印“表格”時,我注意到每次控件從對構造函數的遞歸調用返回時,都會調用析構函數。
輸出片段
Calling hello_world class constructor...
000
A destructor call within initialization has been terminated
001
A destructor call within initialization has been terminated
A destructor call within initialization has been terminated
010
...
...
班級
#define MAX 3
class hello_world
{
char *const buf;
int stack_ptr, destructor_calls;
bool init;
public:
// The recursive constructor
hello_world(char *const &str, int i = 0)
: buf(str), stack_ptr(0), init(false), destructor_calls(0)
{
if (i == MAX)
{
buf[i] = '\0';
cout << buf << endl;
}
else
{
buf[i] = '0';
hello_world::hello_world(str, i + 1);
buf[i] = '1';
hello_world::hello_world(str, i + 1);
}
}
// The recusive destructor
~hello_world()
{
++destructor_calls;
if (!init) { cerr << "A destructor call within initialization has been terminated" << endl; return; }
int i = stack_ptr;
if (i == MAX)
{
buf[i] = '\0';
cout << buf << endl;
}
else
{
buf[i] = '0';
++stack_ptr; // since a destructor cannot take parameters
hello_world::~hello_world();
--stack_ptr;
buf[i] = '1';
++stack_ptr;
hello_world::~hello_world();
--stack_ptr;
// Printing total number of calls at final call
if (i == 0) cout << endl << "\"destrucotr_calls\" = " <<
destructor_calls << endl;
}
}
void unlock()
{
init = true;
}
}; // end of class hello_world
我正在使用int hello_world::stack_ptr
來存儲i
參數的當前數量,因為析構函數不能具有參數。
我的問題是: 為什么每次控件離開對構造函數的遞歸調用時都調用析構函數? 。
這是我的main():
void main()
{
char buf[MAX + 1];
cout << "Calling hello_world class constructor..." << endl;
hello_world h(buf);
h.unlock();
cout << "Calling hello_world class destructor..." << endl;
}
我正在使用VS2010。 您可以在此處查看完整的代碼及其輸出。
添加 :我正嘗試計算具有int hello_world::destructor_calls
的調用析構函數的總數。 我發現打印trauth表算法需要2 * (2^MAX) - 1
調用,最后, destructor_calls
於此值。 但是,在輸出中計算句子"A destructor call within initialization has been terminated"
時,我們發現它已被輸出14次。 因此14(初始化中的調用)+ 15(打印trauth表的自然調用)應該等於29,而destructor_calls
僅等於15(好像在初始化時未調用析構函數!)
沒有遞歸構造函數。 看起來像遞歸實際上是在創建一個新的臨時對象。
可以直接調用析構函數,但是如果您在同一對象上兩次調用析構函數,則會得到未定義的行為,因此無法遞歸調用它。
您需要做的是在構造函數或析構函數內調用另一個成員函數。 然后,您可以使這些其他函數遞歸:
class A {
A() { construct(); }
~A() { destruct(); }
void construct(int i=0) { ... construct(i+1); ... }
void destruct(int i=MAX) { ... destruct(i-1); ... }
};
你玩火...
hello_world::hello_world(str, i + 1);
創建臨時對象然后銷毀它...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.