简体   繁体   中英

Class member suddenly becomes inaccessible/non-existent

In my main, I am calling a function ( func1 )in a loop. This function is a member of Class1 . I am passing an object ( object2 ) of a different class, Class2 to this function. On the first iteration of the loop, the variable var2 (member of Class2 ) is accessible from main, but on the second iteration, it is not. I get an "Access violation reading location" error. Here is what my code looks like:

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

Side note: If I try and print a different variable instead of var2 , it seems to work on the second iteration, so I don't think it's a problem with the object itself.

Thanks in advance!!

The problem is that Class1::func1(Class2 object2) accepts the argument by value. This means that a copy of the Class2 object is being made, and then destructed when func1() returns.

In the Class2 class you do not define a copy constructor, so the compiler is creating one for you that simply copies the members by-value. Then when the copy's destructor runs, it delete s all of the allocations, leaving the original object with a pointer to an invalid object. This is why it fails on the second iteration.

Always follow the rule of three : if you need a custom destructor, copy constructor, or copy assignment operator, you need all three of them . A proper copy constructor will create new allocations for all of the arrays and copy the data to them. (If you are using C++11 then it's actually the rule of five : you probably also want to implement a move constructor and move assignment operator so that you can "steal" the var2 pointer in cases where you know that the object being assigned is an rvalue and therefore will be going away soon anyway.)

In your case, the fix is simple: accept the argument by value:

Class1::func1(Class2 const & object2)

I would strongly suggest using std::vector<std::vector<std::vector<double>>> for your var2 member instead, because then the compiler-generated destructor, copy-constructor, and copy-assignment operator will all do the right thing, and you won't need to implement any of them.

This works hand-in-hand with making func1() accept a reference: while the error is happening because there isn't a custom copy constructor, we really don't even want to make a copy here because we're not modifying the data. Copying the data only to destroy the copy is silly; let's just accept a reference to an existing object instead of requiring a superfluous copy.

Alternatively, you can just disable copying altogether:

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 &);

If you disable copying then you would get a compile-time error on the call object1.func1(object2) because it depends on the existence of a copy-constructor for object2 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM