提问人:joshua 提问时间:8/3/2023 最后编辑:UpAndAdamjoshua 更新时间:8/4/2023 访问量:70
当我遍历 C++ 映射时,为什么它会给我实例化错误?
When I loop through a C++ map, why does it give me an instantiation error?
问:
我正在尝试遍历地图,但我尝试的任何方法似乎都不起作用......我声明并定义地图如下:
// loop through the strings and group based on length
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++) {
^
我错过了什么?
答:
std::map 需要支持以下语义:
NGroup ng& = groups["some key that doesn't exist in this map"];
当键不在映射中时,它默认构造映射的值类型的实例,并将其分配给该键。如果没有默认构造函数,它就不知道要传递给对象的构造函数的内容。
因此,NGroup 需要一个默认构造函数。这为我解决了这个问题:
class NGroup {
public:
vector<string> strings;
vector<AnagramGroup> groups;
NGroup() { // add this
}
此外,NGroup 和 AnagramGroup 都不需要复制构造函数,因为默认构造函数将执行正确的操作。因此,您可以同时删除两者。仅当成员变量无法简单复制或依赖成员变量或成员变量自己的复制构造函数时,才需要复制构造函数。
现在,让我们通过将大多数参数作为 const 引用传递来清理代码的其余部分,这样您就不会无意中复制这些字符串和集合。
class AnagramGroup {
public:
map<char, size_t> freqs;
map<char, size_t> ground;
vector<string> anagrams;
AnagramGroup(const map<char, size_t>& m, const string& anagram) :
freqs(m), ground(m), anagrams({anagram}) {
}
};
class NGroup {
public:
vector<string> strings;
vector<AnagramGroup> groups;
NGroup() {
}
NGroup(const string& str) : strings({ str }) {
}
NGroup(const vector<string>& strs) : strings(strs) {
}
void appendString(const string& str) {
strings.push_back(str);
}
};
评论
NGroup(const vector<string>& strs) : strings(strs) {}
strs
strings
strs
strings
= default
问题在于,你的“复制构造函数”并不是真正的复制构造函数,因为它们通过引用非常量来接受它们的参数。更改复制构造函数以接受对 const 的引用,或者如果它们所做的只是逐个字段的复制,则将其删除,因为编译器将自动生成执行此操作的复制构造函数。
a 的元素是 s,并且是可复制的。当实例化 的复制构造函数时,编译器将提出如下内容:std::map
std::pair
std::pair
std::pair<const size_t, NGroup>
pair(const pair& other)
: first(other.first),
second(other.second)
{}
但是,由于是对 const 的引用,这意味着它是 . 没有接受 a 作为参数的构造函数,因此实例化无效。other
other.second
const NGroup
NGroup
const NGroup
std::pair
评论
Line 19: Char 5: note: candidate constructor not viable: requires single argument 'strs', but no arguments were provided Line 12: Char 7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided Line 12: Char 7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided
no arguments were provided
评论
strs[i]
std::vector<NGroup>