从一道题谈C++容器内元素的类型约束

本文详细解释了在C++中,当类包含const成员变量时,如何正确地定义拷贝赋值函数。通过案例分析,揭示了不定义赋值函数时编译器报错的原因,以及为何在赋值函数中加入打印语句仍无法输出。最终得出结论:对于包含const成员变量的类,必须手动定义赋值函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《C++ primer》第四版中文267页,9.1.2

  • 元素类型必须支持赋值运算。
  • 元素类型的对象必须可以复制。

不久前我复习的时候还标记了一下,没想到理解得还不深刻啊。。

今天算法群有网友提问

类中包含const成员变量时,如何定义 拷贝赋值函数 ? #include <vector> struct Point { Point(int xx, int yy) : x(xx) , y(yy) {} int const x; int const y; }; int main() { std::vector<Point> pts; pts.push_back(Point(0, 0)); return 0; }

这个程序看起来很蛋疼啊, x,y还搞成const...好吧,姑且不说这个了,说一下程序的问题。

这个程序直接编译的话,会有错误

但是加了个赋值函数,里面是空的,就通过编译了

Point& operator= (const Point& p)
{

std::cout << " ok" << std::endl;

}
这个cout语句被没有执行

首先,回到开头我提到的《C++ primer》里面所说的约束条件,放入vector的类一定要支持赋值和复制操作! 但对于一般自己定义的类,我们如果不定义的话,使用系统默认提供的复制和赋值函数就行了,不会有什么问题。但这道题由于使用了const成员变量,又有了其他问题。

“对包含const成员变量的类而言,编译器不提供默认 赋值拷贝 ( = ) 函数的需要自己定义”

http://blog.youkuaiyun.com/cleverwyq/archive/2007/06/23/1663809.aspx

这就解释了为什么我们不定义赋值函数,编译器会报错!

但在赋值函数里面加了cout打印信息,为什么又没有输出呢?
vector.tcc里面的代码不是一般的不好懂, 我还没看STL的源码剖析,所以不敢乱吹。暂时的话,也没有什么兴趣研究(还有另外一个问题,STL怎么实现提供默认的复制赋值函数?)。姑且认为vector会检查复制和赋值函数两个条件吧(注意到出错的提示是在push_back函数。直觉上像是因为调用引起错误的...),因为实际上的的确确没有打印出东西,我们可以肯定程序没有执行进去。我们显式调用赋值函数后,即

pts[0]=Point(2,0);

程序确实有输出。



最后的结论:”对包含const成员变量的类而言,一定记得自己定义赋值函数哦亲”

这道题我之前没能想出来,实在惭愧。我自己平时玩acm,所以还是写c比较多,c++当然也有学。不过,学校的课不要指望能有多深,水得不行。我自己觉得把,编程的话还是得自己多写,在实践中学习那是最好的。类比一个例子,就像背单词一样,拿着单词本背我觉得很不好,很多时候即使看到那个单词,你依然不能断定到底这里面是用了单词的哪个解释;又或者想用一个词的时候,想不起那个词来。一些人原本英语很烂,但出国多年后英语照样杠杠的,我觉得在实际的语境中学语言是最好的,编程也一样!

在群友的追问下,得知这道题的来源..

这个题目是金山的笔试题
编译下面的代码(左侧的数字是行号,并非代码的一部分,文件名为hello.cpp)
1#include<vector>
2
3structPoint{
4Point(intxx,intyy)
5:x(xx)
6,y(yy)
7{}
8
9intconstx;
10intconsty;
11};
12
13intmain()
14{
15std::vector<Point>pts;
16pts.push_back(Point(0,0));
17return0;
18}
会产生类似下面的编译错误
hello.cpp:Inmemberfunction‘Point&Point::operator=(constPoint&)’:
hello.cpp:3:14:
instantiatedfrom`
voidstd::vector<_Tp,_Alloc>::insert(std::vector<_Tp,_Alloc>::iterator,
const_Tp&)
[with
_Tp=Point,
_Alloc=std::allocator<Point>
]'

/usr/include/.../stl_vector.h:??:??:
instantiatedfrom`voidstd::vector<_Tp,_Alloc>::push_back(constvalue_type&)
[with
_Tp=Point,
_Alloc=std::allocator<Point>,
value_type=Point
]'

hello.cpp:16:30:instantiatedfromhere
hello.cpp:3:14:error:non-staticconstmember`constintPoint::x',
can'tusedefaultassignmentoperator
hello.cpp:3:14:error:non-staticconstmember`constintPoint::y',
can'tusedefaultassignmentoperator

Infileincludedfrom/usr/include/...ector:??:??,
fromhello.cpp:1:
/usr/include/...ector.tcc:Inmemberfunction`
voidstd::vector<_Tp,_Alloc>::insert(std::vector<_Tp,_Alloc>::iterator,
const_Tp&)
[with
_Tp=Point,
_Alloc=std::allocator<Point>
]':
/usr/include/...ector.tcc:??:??:note:synthesizedmethod
`Point&Point::operator=(constPoint&)'firstrequiredhere
请问,编译错误要表达什么信息?你会如何修改上述代码以编译通过,同时保持相近的代码意义?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值