int main() {
using kv = std::pair<const int ,int>;
std::vector<kv> vec;
kv a{1,1};
vec.insert(vec.begin(),a);
}
我试图将元素插入该向量,但是编译器给出了此错误消息:
cannot assign to non-static data member 'first' with const-qualified type 'const int'
而push_back()
可以正确编译。为什么?将元素插入到这样的向量中的正确方法是什么?
添加:
我使用std::pair<const int, int>
的原因是我想实现类似std::map
的东西,并且不应修改键值对中的键。但是我不确定std::pair<const int, int>
是否是执行此操作的正确方法。
答案 0 :(得分:8)
让我们从观察以下内容开始:
std::pair<const int, int> a, b;
a=b;
这也不会编译。为什么?因为您实际上是在声明以下类:
class my_pair {
public:
// ... Bunch of irrelevant stuff
const int first;
int second;
};
该类的默认赋值运算符已删除。默认的赋值运算符等效于分别分配类成员:
pair<first,second> &operator=(const pair<first, second> &other)
{
first=other.first;
second=other.second;
return *this;
}
这是默认赋值运算符的大致示例。
但是您不能在这里修改first
类成员,因为它是const
类成员。因此,默认分配运算符被删除。最终结果:无法将具有std::pair
值的const
分配给另一个这样的对。
您现在应该可以自己弄清楚为什么配对向量上的insert()
不起作用。
insert
()大致等效于在插入点之后的向量中将所有现有值平移一个,以便为新值腾出空间。换句话说:
value[n+1]=values[n];
对于超过插入点的所有值(我暂时忽略了将向量增长一个值的工作,这与本次讨论无关)。
但是,正如我所解释的,默认的赋值运算符已删除,因为value
具有一个const
类成员。
push_back
之所以有效,是因为不需要插入任何内容,只需在向量的末尾添加一个新值即可。如果需要重新分配向量以适应其增长,则使用复制或移动构造函数,这些构造函数对于具有std::pair
值的const
仍然有效。
答案 1 :(得分:3)
由于数据类型const
的{{1}}性质(它有一个kv
成员const
),它的复制分配运算符已被隐式删除。编译器。
具体来说,您正在使用的first
的重载要求数据类型(std::vector::insert
)为 CopyAssignable (可以以kv
的形式复制)。您的const成员禁止这样做。
另一方面,a = b
要求类型为 CopyInsertable (可以是复制构造的),您的类型符合。
因此,std::vector::push_back
将不起作用,但insert
将起作用。最简单的解决方法是让push_back
的第一个成员失去const
。如果您不希望有人修改键/值,请不要让他们修改。返回键/值元组时,应将其用作const指针或引用。