簡體   English   中英

C ++:析構函數在它應該超出范圍之前被調用?

[英]C++: Destructor being called before it should go out of scope?

我遇到的問題是在子程序結束時為析類調用析構函數,即使它應該在子程序范圍之外定義。

這是我所擁有的最小的代碼,它顯示了我的問題:

#include <iostream>
using namespace std;

class Foo {
private:

    double *array;

public:

Foo(int N) {
   array = new double[N];
   for (int i=0; i<N; i++) {
       array[i]=0;
   }
}

~Foo() {
   delete[] array;
}
};

void subroutine(Foo x) {
   cout << "Hello!" << endl;
}

int main() {
   Foo bar(10);
   subroutine(bar);
   subroutine(bar);
}

現在,對象欄的析構函數在第一個子例程完成后被調用,即使它的范圍應該是整個main()函數? 這意味着當我調用第二個子例程時,再次調用析構函數並且我得到內存泄漏。

我發現我可以通過在子程序中通過引用調用來解決這個問題,但是我對這個修復不太滿意,因為我不明白為什么它首先不起作用。 任何人都可以為我闡明這一點嗎?

謝謝。

您正在將Foo值傳遞給subroutine函數。 這意味着它有自己的副本,在退出它的范圍時會被銷毀。

void subroutine(Foo x) {
   // x is a new Foo here. It will get destroyed on exiting scope,
   // resulting in a destructor call
}

這里的主要問題是你沒有實現復制構造函數,因此不會復制動態分配的數組(只有指向它的指針)。 因此,當您復制Foo對象時,每個副本都引用相同的數組。 每個副本都會試圖破壞它。

您應該遵循三個規則並實現一個賦值操作符和一個復制構造函數,它們對數組進行“深層復制”,這樣每個Foo對象都擁有自己的數組。

您將按值傳遞到子例程,因此正在創建副本。 為避免副本通過引用傳遞:

void subroutine(Foo& x)
{
    cout << "Hello!" << endl;
}

您可以通過將復制構造函數和復制賦值運算符聲明為私有來防止類的意外副本,如下所示:

class Foo {
private:

    double *array;

    Foo(const Foo&);
    Foo& operator=(const foo&);

public:
    ...
};

然后你得到一個編譯錯誤。 如果你真的需要能夠復制你的類,那么你實際上需要實現這些函數來執行“深層復制”(或者更好的是使用std::vector<float>並讓它為你管理內存包括安全復制)。

當你調用void subroutine(Foo x) {復制你的對象bar (因此在函數完成后調用析構函數)。

嘗試使用: void subroutine(Foo &x) { ,它應該工作得很好。

您遇到的問題是您按值傳遞對象:

void subroutine(Foo x) {

這是創建一個臨時對象,並在每次調用它時調用對象的復制構造函數/析構函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM