2009-10-05 75 views
1

我有以下几点:有问题的std :: multimap中

enum Type 
{ One = 0, Two}; 

class MySubClass 
{ 
private: 
MySubClass(); // prohibited 
MySubClass(const MySubClass&); // prohibited 
MySubClass & operator (const MySubClass&); // prohibited 
public : 
MySubClass(int x); 
}; 

class MyClass 
{ 
MyClass(int x) : m_x(new SubClass(x)) 
{} 
~MyClass() 
{ delete m_x; } 
private : 
MySubClass * m_x; 
}; 

typedef multimap<Type, MyClass> my_multimap; 
typedef pair<Type, MyClass> my_pair; 

我试图做到以下几点:

my_multimap my_map; 
my_map.insert(my_pair(One, MyClass(5))); 

而且我得到一个未处理的异常结果,应用程序试图读取0xfeeefeee等

发生了什么事?我怎样才能解决这个问题? 请注意,这是我正在处理的简化案例;

+1

您不必为“禁止”默认的构造函数,因为提供了一个手写的构造有效地防止编译器生成一个默认的。通过这样做,您可以暴露自己实际上在没有实现后面使用默认构造函数(来自您的班级或朋友)。 – 2009-10-05 12:16:56

回答

4

MyClass没有定义拷贝构造函数。但是,std::pair需要使用MyClass的复制构造函数。据推测,它是使用MyClass的默认拷贝构造函数,这将给指针m_x的拷贝构造的对象副本。当它们被破坏时,你将面临多次删除。

1

你必须写一个拷贝构造函数。

发生了什么事情,MyClass被值 复制,指针在副本之间共享。 现在,当对象被销毁的 指针被删除multiplie倍。

像这样:

class MyClass 
{ 
MyClass(int x) : m_x(new SubClass(x)) {} 
MyClass(const MyClass& myclass) : m_x(new SubClass(*myclass.m_x)) {} 
~MyClass() { delete m_x; } 
private : 
MySubClass * m_x; 
}; 

显然子类需要一个拷贝构造函数了。

+0

尽管它可能不会用于显示的代码中,但仍会遗漏赋值运算符。此外,派生类不需要定义复制构造函数,编译器生成的就没问题。 – sbi 2015-07-02 11:25:10

5

有一个经验法则,叫“规则三”:只要你有一张析构函数或赋值运算符或拷贝构造函数,它很可能你会需要他们三个。你的代码也不是这个规则的例外。

想象一下如果你的类型的对象复制会发生什么。这

MyClass obj1; 
MyClass obj2(obj1); 

代码也会崩溃。

1

正如大家提到的,类需要一个工作拷贝构造函数才能存储在任何标准容器中。但是,在这种情况下,MySubClass会禁用复制。这几乎给你两个选择:

1)MyClass也应该是不可复制的,在这种情况下,你必须在multimap中存储(智能)指针。

2)复制的MyClass实例应共享MySubClass实例。为了实现这一点,最简单的就是用boost::shared_ptr<MySubClass>std::tr1::shared_ptr<MySubClass>更换指针成员。这样做可以使您免于执行析构函数,复制构造函数和赋值运算符。