为什么我需要声明默认构造函数以便在返回 unordered_map 值时进行编译?
Why do I need to declare a default constructor in order to compile when returning an unordered_map value?
除非我取消注释默认构造函数声明,否则此示例无法编译:
#include<unordered_map>
#include <iostream>
struct foo{
int data;
/*foo(){
data = 0;
std::cout << "DEFAULT\n";
}*/
foo(int d){
data = d;
std::cout << "PARAM\n";
}
};
struct bar{
std::unordered_map<int, foo> map;
foo getElem(int i){
return map[i];
}
};
int main() {
bar b;
foo f1(1);
foo f2(2);
b.map.insert({1,f1});
b.map.insert({2,f2});
foo f3 = b.getElem(1);
}
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/tuple:1689:70: error: no matching function for call to 'foo::foo()'
1689 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
| ^
当我取消注释默认构造函数声明并成功编译时,面包屑显示从未调用过默认构造函数。
这是怎么回事?类似的问题是由于 most vexing parse,但没有任何显式构造函数调用,我不确定这里是否是这种情况。
提供了关于为什么 unordered_map 会隐式调用默认构造函数的提示。问题是描述的记录行为和 MVP 的某种组合吗?
当编译器编译这一行时:
foo f3 = b.getElem(1);
1
作为参数传递给函数(除非发生大量优化魔术,但不能保证)。此函数无法知道 1
永远不会是丢失的键。因此,调用映射中分配条目的代码。如果密钥丢失,传递给此代码的是什么?是的,一个默认构造的 foo
.
所以,简而言之,你知道
the default constructor is not ever called
但编译器和链接器没有。
除非我取消注释默认构造函数声明,否则此示例无法编译:
#include<unordered_map>
#include <iostream>
struct foo{
int data;
/*foo(){
data = 0;
std::cout << "DEFAULT\n";
}*/
foo(int d){
data = d;
std::cout << "PARAM\n";
}
};
struct bar{
std::unordered_map<int, foo> map;
foo getElem(int i){
return map[i];
}
};
int main() {
bar b;
foo f1(1);
foo f2(2);
b.map.insert({1,f1});
b.map.insert({2,f2});
foo f3 = b.getElem(1);
}
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/tuple:1689:70: error: no matching function for call to 'foo::foo()'
1689 | second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
| ^
当我取消注释默认构造函数声明并成功编译时,面包屑显示从未调用过默认构造函数。
这是怎么回事?类似的问题是由于 most vexing parse,但没有任何显式构造函数调用,我不确定这里是否是这种情况。
当编译器编译这一行时:
foo f3 = b.getElem(1);
1
作为参数传递给函数(除非发生大量优化魔术,但不能保证)。此函数无法知道 1
永远不会是丢失的键。因此,调用映射中分配条目的代码。如果密钥丢失,传递给此代码的是什么?是的,一个默认构造的 foo
.
所以,简而言之,你知道
the default constructor is not ever called
但编译器和链接器没有。