繁体   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