首页 > 解决方案 > 为什么在返回 unordered_map 值时需要声明默认构造函数才能编译?

问题描述

除非我取消注释默认构造函数声明,否则此示例无法编译:

#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))...)
      |                                                                      ^

当我取消注释默认构造函数声明并成功编译时,面包屑显示从未调用过默认构造函数。

这里发生了什么?类似的问题是由于最令人烦恼的 parse,但没​​有任何显式的构造函数调用,我不确定这里是否是这种情况。

这个答案提供了关于为什么 unordered_map 会隐式调用默认构造函数的提示。问题是所描述的记录行为和 MVP 的某种组合吗?

链接到神螺栓

标签: c++unordered-mapdefault-constructormost-vexing-parse

解决方案


当编译器编译这一行时:

foo f3 = b.getElem(1);

1作为参数传递给函数(除非发生了很多优化魔法,这是不能保证的)。此函数无法知道1永远不会丢失密钥。因此,调用在映射中分配条目的代码。如果缺少密钥,则传递给此代码的内容是什么?是的,一个默认构造的foo.

所以,简而言之,你知道

从未调用过默认构造函数

但编译器和链接器没有。


推荐阅读