首先,我有下面的类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,在调试时我发现:
b
result
成员在返回调用复制构造函数时,指向 [1] 中b
指向的同一地址 [2] 中的陈述,到目前为止一直很好
在 [2] 返回之前b
的内容是正确的,例如:0x00669968 00 00 ff 00 00 ff 00 00 ..ÿ..ÿ..
在 [3] 之后 [1] 中的b
的内容以及b
result
成员的内容1}}对象变成类似:0x00669968 dd dd dd dd dd dd dd dd ÝÝÝÝÝÝÝÝ
,我猜测是垃圾
注意:所有include
指令和不相关的代码段都已被省略
我已经两天摇头想要找出没有运气的错误,所以非常感谢任何帮助,非常感谢。
答案 0 :(得分:1)
我检查了您的代码,问题是您需要class A
的自定义副本分配。在你的主体中你有A a1, a2, result;
,为3个对象调用默认构造函数。然后,在行result = a1 + a2;
中,调用默认的副本分配。
如果在类中有指针并使用new分配内存,则必须担心复制构造函数和复制赋值。查看this post和the 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();
}
};