不是一个重大问题,只是烦人,因为我不希望我的类在没有特定参数的情况下被实例化。
#include <map>
struct MyClass
{
MyClass(int t);
};
int main() {
std::map<int, MyClass> myMap;
myMap[14] = MyClass(42);
}
这给了我以下g ++错误:
/ usr / include / c ++ / 4.3 / bits / stl_map.h:419:错误:没有用于调用'MyClass()'的匹配函数
如果添加默认构造函数,则编译正常;我确信它不是由不正确的语法引起的。
答案 0 :(得分:141)
此问题随运营商[]提供。引自SGI文档:
data_type& operator[](const key_type& k)
- 返回对象的引用 与特定的相关联 键。如果地图还没有 包含这样的对象,operator[]
插入默认对象data_type()
。
如果您没有默认构造函数,则可以使用insert / find函数。 以下示例正常工作:
myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;
答案 1 :(得分:6)
<击>是。 STL容器中的值需要维护复制语义。 IOW,它们需要表现得像原始类型(例如int),这意味着,除其他外,它们应该是默认构造的。
如果没有这个(和其他要求),在实现STL容器的数据结构上实现各种内部复制/移动/交换/比较操作将是不必要的。
击>
在参考C ++标准时,我看到我的回答并不准确。 默认构造实际上不是要求:
从20.1.4.1开始:
默认构造函数不是 需要。某些容器类 成员函数签名指定 默认构造函数作为默认值 论点。 T()必须是一个定义明确的 表达......
因此,严格地说,如果您碰巧使用在其签名中使用默认构造函数的容器函数,则您的值类型只需要是默认构造的。
存储在STL容器中的所有值的实际要求(23.1.3)为CopyConstructible
和Assignable
。
对于特定容器也有其他特定要求,例如Comparable
(例如,地图中的键)。
顺便提一下,以下内容在comeau上编译时没有错误:
#include <map>
class MyClass
{
public:
MyClass(int t);
};
int main()
{
std::map<int, MyClass> myMap;
}
所以这可能是一个g ++问题。
答案 2 :(得分:2)
检查stl :: map的存储类型的要求。许多stl集合要求存储类型包含一些特定属性(默认构造函数,复制构造函数等)。
stl :: map需要没有参数的构造函数,因为当使用键调用operator []时,它会被使用,而键尚未被映射保留。在这种情况下,operator []插入新条目,该条目包含使用无参数构造函数构造的新键和值。然后返回这个新值。
答案 3 :(得分:-1)
检查是否:
我认为std :: map声明似乎是正确的。
答案 4 :(得分:-1)
很可能是因为std :: pair需要它。 std :: pair使用值语义来保存两个值,因此您需要能够在没有参数的情况下实例化它们。因此代码在各个地方使用std :: pair将映射值返回给调用者,这通常通过实例化一个空对并在返回本地对之前将值分配给它来完成。
你可以使用智能指针来解决这个问题,使用地图&lt; int,smartptr&lt; MyClass&gt; &GT;但这增加了检查空指针的开销。