遍历C++ map触发实例化错误的原因排查
问题:遍历C++ map时触发拷贝构造函数错误
我定义了一个map<size_t, NGroup>用于按字符串长度分组,填充代码如下:
// 遍历字符串并按长度分组 map<size_t, NGroup> groups; for (size_t i = 0; i < strs.size(); i++) { size_t len = strs[i].size(); if (groups.count(len) != 0) { groups.at(len).appendString(strs[i]); } else { NGroup g(strs[i]); groups[len] = g; } }
相关类定义:
class AnagramGroup { public: map<char, size_t> freqs; map<char, size_t> ground; vector<string> anagrams; AnagramGroup(map<char, size_t> m, string anagram) { freqs = m; ground = m; anagrams.push_back(anagram); } AnagramGroup(AnagramGroup &other); }; class NGroup { public: vector<string> strings; vector<AnagramGroup> groups; NGroup(string str) { vector<string> strs = {str}; strings = strs; } NGroup(vector<string> strs) { strings = strs; } NGroup(NGroup &other); void appendString(string str) { strings.push_back(str); } };
尝试两种遍历方式:
map<size_t, NGroup>::iterator it; for (it = groups.begin(); it != groups.end(); it++) { ... }
for (const auto &p : groups) { ... }
均触发相同错误:
In file included from prog_joined.cpp:1: In file included from ./precompiled/headers.h:13: In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/cmath:1927: In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/specfun.h:45: In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_algobase.h:64: /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_pair.h:303:17: error: the parameter for this explicitly-defaulted copy constructor is const, but a member or base requires it to be non-const constexpr pair(const pair&) = default; ^ Line 61: Char 38: note: in instantiation of template class 'std::pair<const unsigned long, NGroup>' requested here for (it = groups.begin(); it != groups.end(); it++) { ^
请问忽略了什么?
原因与解决方案
问题根源
错误核心在于自定义类的拷贝构造函数参数未使用const引用:
AnagramGroup和NGroup声明的拷贝构造函数,参数是非const的左值引用(AnagramGroup(AnagramGroup &other)、NGroup(NGroup &other))。- STL容器(如
map)的元素是std::pair<const Key, Value>,当容器需要拷贝该pair时,会调用Value(即NGroup)的拷贝构造函数。但std::pair的默认拷贝构造函数接受const引用,而你的NGroup拷贝构造仅支持非const引用,导致类型不匹配,触发编译错误。
解决方案
修改两个类的拷贝构造函数,将参数改为const左值引用:
class AnagramGroup { // ... 其他成员 AnagramGroup(const AnagramGroup &other); }; class NGroup { // ... 其他成员 NGroup(const NGroup &other); };
若无需自定义拷贝逻辑,可直接让编译器生成默认的拷贝构造函数,更简洁:
class AnagramGroup { // ... 其他成员 AnagramGroup(const AnagramGroup &other) = default; }; class NGroup { // ... 其他成员 NGroup(const NGroup &other) = default; };
也可直接删除拷贝构造函数的声明,编译器会自动生成符合要求的默认版本。
额外优化建议
填充map时,groups[len] = g;会先默认构造NGroup再赋值,可改用emplace直接在容器内构造对象,避免不必要的拷贝:
groups.emplace(len, strs[i]);
内容的提问来源于stack exchange,提问作者joshua
相关产品推荐
相关产品推荐

