[英]Class member suddenly becomes inaccessible/non-existent
我主要是在循環中調用一個函數( func1
)。 該函數是Class1
的成員。 我正在將不同類Class2
的對象( object2
)傳遞給此函數。 在循環的第一次迭代中,可以從main訪問變量var2
( Class2
成員),但是在第二次迭代中則不能。 我收到“訪問沖突讀取位置”錯誤。 這是我的代碼:
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.