返回后重写的数组内容

时间:2016-06-20 22:10:34

标签: c++ copy-constructor

首先,我有下面的类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;
};

我尝试使用重载的+运算符来"添加"两个A个对象,添加所述对象的b个成员的内容,并将结果分配给第三个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. b result成员在返回调用复制构造函数时,指向 [1] b指向的同一地址 [2] 中的陈述,到目前为止一直很好

  2. [2] 返回之前b的内容是正确的,例如:0x00669968 00 00 ff 00 00 ff 00 00 ..ÿ..ÿ..

  3. [3] 之后 [1] 中的b的内容以及b result成员的内容1}}对象变成类似:0x00669968 dd dd dd dd dd dd dd dd ÝÝÝÝÝÝÝÝ,我猜测是垃圾

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

    我已经两天摇头想要找出没有运气的错误,所以非常感谢任何帮助,非常感谢。

1 个答案:

答案 0 :(得分: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();
    }
};