簡體   English   中英

班級成員突然變得無法訪問/不存在

[英]Class member suddenly becomes inaccessible/non-existent

我主要是在循環中調用一個函數( func1 )。 該函數是Class1的成員。 我正在將不同類Class2的對象( object2 )傳遞給此函數。 在循環的第一次迭代中,可以從main訪問變量var2Class2成員),但是在第二次迭代中則不能。 我收到“訪問沖突讀取位置”錯誤。 這是我的代碼:

main.cpp:

#include "Class1.h"
int main(){

    Class2 object2;
    object2.assign_var2();
    Class1 object1;


    for (int i = 0; i < 2; ++i){
        std::cout << object2.var[0][0][0] << std::endl; // Works ONLY on first iteration
        object1.func1(object2)
    }
}

Class2.h:

class Class2{
    ... other variables and functions declared
    public:
    Class2::Class2();
    Class2::~Class2();
    double *** var2;
    void assign_var2();
}

Class2.cpp:

Class2::Class2(){

var2 = new double**[200];
for (int i = 0; i < 200; ++i) {
    var2[i] = new double*[200];

    for (int j = 0; j < 200; ++j){
    var2[i][j] = new double[2];
    }
}

Class2::~Class2(){
for (int i = 0; i < 200; ++i){
    for (int j = 0; j < 200; ++j){
        delete [] var2[i][j];
    }
    delete [] var2[i];
}
delete [] var2;
}

void assign_var2(){
for (int i = 0; i<200; ++i){
    for (int j = 0; j<200; ++j){

        var2[i][j][0] = some_number1;
        var2[i][j][1] = some_number2;
    }
}
}
}

Class1.h:

#include "Class2.h"
class Class1{
    ... other variables, functions declared
    public:
    void func1(Class2)

}

Class1.cpp:

Class1::func1(Class2 object2){
    int u = object2.var2[1][2][0];
    int v = object2.var2[1][2][1];
}

旁注:如果我嘗試打印一個不同的變量而不是var2 ,那么它似乎可以在第二次迭代中使用,因此我認為對象本身沒有問題。

提前致謝!!

問題是Class1::func1(Class2 object2)按值接受參數。 這意味着將創建Class2對象的副本,然后在func1()返回時銷毀該副本。

Class2類中,您沒有定義復制構造函數,因此編譯器將為您創建一個僅按成員復制成員的值。 然后,當副本的析構函數運行時,它將delete所有分配,使原始對象具有指向無效對象的指針。 這就是為什么它在第二次迭代中失敗。

始終遵循三個規則 :如果需要自定義析構函數,復制構造函數或復制賦值運算符,則需要全部三個 適當的復制構造函數將為所有數組創建新分配,並將數據復制到它們。 (如果您使用的是C ++ 11,那么實際上這是五個規則 :您可能還希望實現move構造函數和move賦值運算符,以便在知道對象已被賦值的情況下“竊取” var2指針。是右值,因此無論如何很快就會消失。)

就您而言,解決方法很簡單:按值接受參數:

Class1::func1(Class2 const & object2)

我強烈建議為您的var2成員改用std::vector<std::vector<std::vector<double>>> ,因為那樣編譯器生成的析構函數,復制構造函數和復制賦值運算符都可以正確的事情,您將不需要實施其中任何一個。

這與使func1()接受引用func1() :雖然發生錯誤是因為沒有自定義副本構造函數,但我們實際上根本不想在這里創建副本,因為我們沒有修改數據。 僅為了破壞副本而復制數據是愚蠢的。 讓我們只接受對現有對象的引用,而不需要多余的副本。

或者,您可以完全禁用復制:

class Class2 {
    // ...

    // For C++11: explicitly delete the copy-ctor and copy-assignment operator.
public:
    Class2(Class2 const &) = delete;
    Class2 & operator=(Class2 const &) = delete;

    // For C++03: declare the copy-ctor and copy-assignment operator private and
    // then do not implement them. (C++03 doesn't have the "= delete" syntax.)
private:
    Class2(Class2 const &);
    Class2 & operator=(Class2 const &);

如果禁用然后復制你會得到關於調用編譯時錯誤object1.func1(object2)因為它依賴於一個拷貝構造函數存在object2

暫無
暫無

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

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