我遇到以下错误。
Foo
。此类的实例存储在vec
的std :: vector class B
中。new
分配内存并在~Foo()
中删除该对象来创建A类实例。 代码编译,但我在运行时崩溃了。如果我从类delete my_a
的desstructor中禁用Foo
。代码运行正常(但会有内存泄漏)。
有人可以解释一下这里出了什么问题并建议修复吗?
谢谢你!class A{
public:
A(int val);
~A(){};
int val_a;
};
A::A(int val){
val_a = val;
};
class Foo {
public:
Foo();
~Foo();
void createA();
A* my_a;
};
Foo::Foo(){
createA();
};
void Foo::createA(){
my_a = new A(20);
};
Foo::~Foo(){
delete my_a;
};
class B {
public:
vector<Foo> vec;
void createFoo();
B(){};
~B(){};
};
void B::createFoo(){
vec.push_back(Foo());
};
int main(){
B b;
int i =0;
for (i = 0; i < 5; i ++){
std::cout<<"\n creating Foo";
b.createFoo();
std::cout<<"\n Foo created";
}
std::cout<<"\nDone with Foo creation";
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
答案 0 :(得分:7)
您需要为Foo实现复制构造函数和赋值运算符。每当你发现你需要一个析构函数时,你几乎肯定也需要这两个。它们在很多地方使用,特别是用于将对象放入标准库容器中。
复制构造函数应如下所示:
Foo :: Foo( const Foo & f ) : my_a( new A( * f.my_a ) ) {
}
和赋值运算符:
Foo & Foo :: operator=( const Foo & f ) {
delete my_a;
my_a = new A( * f.my_a );
return * this;
}
或者更好的是,不要动态地在Foo类中创建A实例:
class Foo {
public:
Foo();
~Foo();
void createA();
A my_a;
};
Foo::Foo() : my_a( 20 ) {
};
答案 1 :(得分:3)
如果您没有指定复制构造函数,编译器会为您创建一个。编译器生成的复制构造函数如下所示:
Foo::Foo(const Foo& copy)
: my_a(copy.my_a)
{}
Woops!你只是复制指针而不是指向内存。 Foo()
中的临时createFoo()
和复制到矢量中的临时Foo::Foo(const Foo& copy)
: my_a(new A(*copy.my_a))
{}
都指向相同的内存,因此内存将被删除两次,这会在第二次删除时崩溃。
您应该创建一个类似于以下内容的复制构造函数:
copy
请注意,如果my_a
具有NULL A
成员,则会崩溃,并且它还会调用operator=
上的复制构造函数,但您尚未指定。因此,您需要进行一些进一步的更改。您也需要{{1}}重载。
答案 2 :(得分:2)
复制Foo对象,并在销毁每个副本时,在相同的指针值my_a上调用delete。 为Foo实现复制和赋值运算符或使用智能指针。
Foo( const Foo& s) : my_a( s.my_a ? new A(*s.my_a) : 0) {
}
Foo& operator= (const Foo& s) {
Foo temp(s);
temp.swap (*this);
return *this;
}
void swap (Foo &s) {
std::swap (my_a, s.my_a);
};