为什么 C++ 映射类型参数在使用 [] 时需要一个空的构造函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/695645/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does the C++ map type argument require an empty constructor when using []?
提问by Nick Bolton
另请参见 C++ 标准列表和默认构造类型
Not a major issue, just annoying as I don't want my class to ever be instantiated without the particular arguments.
不是主要问题,只是烦人,因为我不希望我的类在没有特定参数的情况下被实例化。
#include <map>
struct MyClass
{
MyClass(int t);
};
int main() {
std::map<int, MyClass> myMap;
myMap[14] = MyClass(42);
}
This gives me the following g++ error:
这给了我以下 g++ 错误:
/usr/include/c++/4.3/bits/stl_map.h:419: error: no matching function for call to ‘MyClass()'
/usr/include/c++/4.3/bits/stl_map.h:419: 错误:没有匹配的函数调用“MyClass()”
This compiles fine if I add a default constructor; I am certain it's not caused by incorrect syntax.
如果我添加一个默认构造函数,这编译得很好;我确定这不是由不正确的语法引起的。
回答by bayda
This issue comes with operator[]. Quote from SGI documentation:
这个问题来自于 operator[]。引用自 SGI 文档:
data_type& operator[](const key_type& k)
- Returns a reference to the object that is associated with a particular key. If the map does not already contain such an object,operator[]
inserts the default objectdata_type()
.
data_type& operator[](const key_type& k)
- 返回对与特定键关联的对象的引用。如果地图尚未包含此类对象,则operator[]
插入默认对象data_type()
。
If you don't have default constructor you can use insert/find functions. Following example works fine:
如果您没有默认构造函数,则可以使用插入/查找函数。以下示例工作正常:
myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;
回答by Assaf Lavie
Yes. Values in STL containers need to maintain copy semantics. IOW, they need to behave like primitive types (e.g. int) which means, among other things, they should be default-constructible.
是的。STL 容器中的值需要维护复制语义。IOW,它们需要表现得像原始类型(例如 int),这意味着除其他外,它们应该是默认构造的。
Without this (and others requirements) it would be needlessly hard to implement the various internal copy/move/swap/compare operations on the data structures with which STL containers are implemented.
如果没有这个(和其他要求),在实现 STL 容器的数据结构上实现各种内部复制/移动/交换/比较操作将是不必要的困难。
Upon reference to the C++ Standard, I see my answer was not accurate. Default-construction is, in fact, not a requirement:
在参考 C++ 标准时,我发现我的答案不准确。事实上,默认构造不是必需的:
From 20.1.4.1:
从 20.1.4.1 开始:
The default constructor is not required. Certain container class member function signatures specify the default constructor as a default argument. T() must be a well-defined expression ...
不需要默认构造函数。某些容器类成员函数签名将默认构造函数指定为默认参数。T() 必须是一个定义良好的表达式...
So, strictly speaking, your value type only needs to be default constructible if you happen to be using a function of the container that uses the default constructor in its signature.
因此,严格来说,如果您碰巧使用在其签名中使用默认构造函数的容器函数,则您的值类型只需要是默认可构造的。
The real requirements (23.1.3) from all values stored in STL containers are CopyConstructible
and Assignable
.
存储在 STL 容器中的所有值的真正要求 (23.1.3) 是CopyConstructible
和Assignable
。
There are also other specific requirements for particular containers as well, such as being Comparable
(e.g. for keys in a map).
对于特定容器也有其他特定要求,例如存在Comparable
(例如对于地图中的键)。
Incidentally, the following compiles with no error on comeau:
顺便说一句,以下编译在comeau上没有错误:
#include <map>
class MyClass
{
public:
MyClass(int t);
};
int main()
{
std::map<int, MyClass> myMap;
}
So this might be a g++ problem.
所以这可能是一个 g++ 问题。
回答by oo_olo_oo
Check requirements of stored type of the stl::map. Many stl collection require that stored type contains some specific properties (default constructor, copy constructor, etc.).
检查 stl::map 的存储类型要求。许多 stl 集合要求存储类型包含一些特定的属性(默认构造函数、复制构造函数等)。
Constructor without arguments is needed by the stl::map, because it's used, when operator[] is invoked with the key, which hasn't already been kept by the map. In this case the operator[] inserts the new entry consisting of the new key and value constructed using parameterless constructor. And this new value is then returned.
stl::map 需要不带参数的构造函数,因为当使用 key 调用 operator[] 时会使用它,而 map 尚未保留该键。在这种情况下,operator[] 插入由使用无参数构造函数构造的新键和值组成的新条目。然后返回这个新值。
回答by Hernán
Check if:
检查是否:
- You forgot the ';' after class declaration.
- MyType should've been declared accordingly.
- No default constructor there...
- 你忘了';' 类声明后。
- MyType 应该相应地声明。
- 那里没有默认构造函数...
The std::map declaration seems correct, I think.
我认为 std::map 声明似乎是正确的。
回答by jmucchiello
Most likely because std::pair requires it. std::pair holds two values using value semantics so you need to be able to instantiate them without parameters. So the code uses std::pair in various places to return the map values to the caller and this is commonly done by instantiating an empty pair and assigning the values into it before returning the local pair.
很可能是因为 std::pair 需要它。std::pair 使用值语义保存两个值,因此您需要能够在没有参数的情况下实例化它们。所以代码在不同的地方使用 std::pair 将映射值返回给调用者,这通常是通过实例化一个空对并在返回本地对之前将值分配给它来完成的。
You could get around this with smart pointers using a map<int, smartptr<MyClass> > but that adds the overhead of checking for null pointers.
您可以使用 map<int, smartptr<MyClass> > 使用智能指针解决此问题,但这会增加检查空指针的开销。