简体   繁体   English

班级成员突然变得无法访问/不存在

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

In my main, I am calling a function ( func1 )in a loop. 我主要是在循环中调用一个函数( func1 )。 This function is a member of Class1 . 该函数是Class1的成员。 I am passing an object ( object2 ) of a different class, Class2 to this function. 我正在将不同类Class2的对象( object2 )传递给此函数。 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. 在循环的第一次迭代中,可以从main访问变量var2Class2成员),但是在第二次迭代中则不能。 I get an "Access violation reading location" error. 我收到“访问冲突读取位置”错误。 Here is what my code looks like: 这是我的代码:

main.cpp: 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: Class2.h:

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

Class2.cpp: 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: Class1.h:

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

} }

Class1.cpp: 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. 旁注:如果我尝试打印一个不同的变量而不是var2 ,那么它似乎可以在第二次迭代中使用,因此我认为对象本身没有问题。

Thanks in advance!! 提前致谢!!

The problem is that Class1::func1(Class2 object2) accepts the argument by value. 问题是Class1::func1(Class2 object2)按值接受参数。 This means that a copy of the Class2 object is being made, and then destructed when func1() returns. 这意味着将创建Class2对象的副本,然后在func1()返回时销毁该副本。

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. Class2类中,您没有定义复制构造函数,因此编译器将为您创建一个仅按成员复制成员的值。 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. 然后,当副本的析构函数运行时,它将delete所有分配,使原始对象具有指向无效对象的指针。 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.) (如果您使用的是C ++ 11,那么实际上这是五个规则 :您可能还希望实现move构造函数和move赋值运算符,以便在知道对象已被赋值的情况下“窃取” var2指针。是右值,因此无论如何很快就会消失。)

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. 我强烈建议为您的var2成员改用std::vector<std::vector<std::vector<double>>> ,因为那样编译器生成的析构函数,复制构造函数和复制赋值运算符都可以正确的事情,您将不需要实施其中任何一个。

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. 这与使func1()接受引用func1() :虽然发生错误是因为没有自定义副本构造函数,但我们实际上根本不想在这里创建副本,因为我们没有修改数据。 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 . 如果禁用然后复制你会得到关于调用编译时错误object1.func1(object2)因为它依赖于一个拷贝构造函数存在object2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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