【问题标题】:Content of array being rewritten after return返回后重写的数组内容
【发布时间】:2016-06-20 22:10:34
【问题描述】:

首先,我有下面的类A,同时还有一个嵌套类B

// A.h
class A {
public:
    class B;

    A();
    A(const A& a); // Copy constructor

    B& operator[](const unsigned int& a) const;
    A operator+(const A& a) const;

    /*...*/

    ~A();
private:
    /*...*/
    unsigned int size;
    B* b;
};

我正在尝试使用重载的+ 运算符通过添加所述对象的两个b 成员的内容来“添加”两个A 对象,并将结果分配给第三个A 对象.

  • b 是一个动态分配的 B 对象数组。

  • B 是一个非常基础的类,只有一些 unsigned int

这里是主要功能:

// main.cpp
int main(int argc, char** argv) {
    A a1, a2, result;

    a1.read(argv[1]); // Initialize b member with content read from a file
    a2.read(argv[2]); // Initialize b member with content read from a file

    result = a1 + a2; // Error [3]

    getchar();

    return 0;
}

问题是,当我尝试求和时,我得到了我认为的内存错误,例如:HEAP[main.exe]: Invalid address specified to RtlValidateHeap( 00A50000, 00A59938 )

这是A类的实现:

// A.cpp
A::A() : /*...*/, size(0), b(nullptr) {}

// Copy constructor
A::A(const A& a) : /*...*/, size(a.size), b(nullptr) {
    b = new B[size]; // [1]

    for (unsigned int i = 0; i < size; i++) {
        (*this)[i] = a[i];
    }
}

A::B& A::operator[](const unsigned int& i) const {
    return b[i];
}

A A::operator+(const A& a) const {
    if (size != a.size) {
        exit(1); // Size must be the same on both operands
    }

    A tmp(*this); // Call to copy constructor

    for (unsigned int i = 0; i < a.size; i++) {
        tmp[i] += a[i];
    }

    return tmp; // Call to copy constructor [2]
}

A::~A() {
    if (b != nullptr) {
        delete[] b;
    }
}

B:

// B.h
class A::B {
public:
    B();
    B(unsigned char, unsigned char, unsigned char);

    B& operator+=(const B& b);
private:
    unsigned int a, b, c, d;
};

// B.cpp
A::B::B() : a(0), b(0), c(0), d(0) {}
A::B::B(unsigned char _a, unsigned char _b, unsigned char _c) {
    /*...*/
}

A::B& A::B::operator+=(const B& b) {
    /*...*/

    return *this;
}

顺便说一句,我正在使用 Visual Studio,在调试时我观察到:

  1. result 的成员result 指向[1]b 指向的同一地址,当[ 中的return 语句调用复制构造函数时2],到目前为止一切顺利

  2. 直到在[2]中返回b的内容就可以了,比如:0x00669968 00 00 ff 00 00 ff 00 00 ..ÿ..ÿ..

  3. [3] 之后 [1]b 的内容,因此result 对象的b 成员的内容变成了什么like:0x00669968 dd dd dd dd dd dd dd dd ÝÝÝÝÝÝÝÝ,我猜是垃圾

注意:所有include 指令和不相关的代码部分都已被省略

我已经连续两天摇头试图找出没有运气的问题所以非常感谢任何帮助,在此先感谢。

【问题讨论】:

  • 我看到的问题是,当athis 具有不同的大小时,它在函数A A::operator+(const A&amp; a) const 中,您将读取无效地址。您需要限制两个 A 对象的大小必须相等。
  • 可以添加class B的定义。
  • @chema989 感谢您的帮助,尽管我所做的每次尝试都使用相同大小的对象,无论如何我已经更新了具有该限制的代码以反映您所说的内容并添加了类的定义B
  • 您应该在创建tmp 对象之前验证this-&gt;size != a.sizeimg.size 应该是 a.size。但更重要的是,A::read() 是如何操作b 数组的?您可能在调用 operator+ 之前损坏了数组。另外,另外,operator+ 应该在A 内部实现为operator+=(就像你对B::operator+= 所做的那样,然后你应该定义一个单独的非成员operator+ 来添加两个@ 987654366@s 一起。

标签: c++ copy-constructor


【解决方案1】:

我检查了您的代码,问题是您需要为 class A 自定义复制分配。在您的主目录中,您有 A a1, a2, result;,为 3 个对象调用了默认构造函数。然后,在result = a1 + a2; 行中,调用了默认的复制分配。

当您的类中有指针并使用 new 分配内存时,您必须担心复制构造函数和复制分配。检查this postthe rule of three


我建议你下一个代码:

class A {
    class B {
        unsigned a, b, c, d;

    public:
        B() : a(0), b(0), c(0), d(0) { }

        B(unsigned char a_, unsigned char b_, unsigned char c_) : a(a_), b(b_), c(c_), d(0) { }

        // Copy constructor.
        B& operator=(const B& b_) {
            a = b_.a;
            b = b_.b;
            c = b_.c;
            d = b_.d;
            return *this;
        }

        B& operator+=(const B& b_) {
            a += b_.a;
            b += b_.b;
            c += b_.c;
            d += b_.d;
            return *this;
        }
    };

    unsigned size;
    B* b;

public:
    A() : size(0) { }

    // Copy constructor.
    A(const A& a) : size(a.size) {
        b = new B[size];
        for (unsigned i = 0; i < size; ++i) {
            b[i] = a[i];
        }
    }

    // Copy assigment
    A& operator=(const A& a) {
        clear();
        b = new B[size];
        for (unsigned i = 0; i < size; ++i) {
            b[i] = a[i];
        }
        return *this;
    }

    B& operator[](unsigned pos) const {
        if (pos > size) {
            throw std::out_of_range("Out of range");
        }
        return b[pos];
    }

    A operator+(const A& a) const {
        A tmp = *this;
        if (size != a.size) {
            throw std::out_of_range("Diferent sizes");
        }
        for (unsigned i = 0; i < a.size; ++i) {
            tmp[i] += a[i];
        }
        return tmp;
    }

    void read(const char* file) {
        clear();
        size = size_;
        b = new B[size];
        /*
         * Read your file and update b.
         */
    }

    void clear() {
        if (size) {
            delete[] b;
            size = 0;
        }
    }

    ~A() {
        clear();
    }
};

【讨论】:

  • 同意问题是缺少A::operator=;但是 OP 表示他们希望 B 从标题中隐藏
  • 完美,我肯定错过了复制赋值运算符,也感谢您的提示!
猜你喜欢
  • 2021-10-19
  • 1970-01-01
  • 2014-11-28
  • 1970-01-01
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
相关资源
最近更新 更多