《C++ primer》第四版中文267页,9.1.2
- 元素类型必须支持赋值运算。
- 元素类型的对象必须可以复制。
不久前我复习的时候还标记了一下,没想到理解得还不深刻啊。。
今天算法群有网友提问
这个程序看起来很蛋疼啊, 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函数。直觉上像是因为调用引起错误的...),因为实际上的的确确没有打印出东西,我们可以肯定程序没有执行进去。我们显式调用赋值函数后,即
程序确实有输出。
最后的结论:”对包含const成员变量的类而言,一定记得自己定义赋值函数哦亲”
这道题我之前没能想出来,实在惭愧。我自己平时玩acm,所以还是写c比较多,c++当然也有学。不过,学校的课不要指望能有多深,水得不行。我自己觉得把,编程的话还是得自己多写,在实践中学习那是最好的。类比一个例子,就像背单词一样,拿着单词本背我觉得很不好,很多时候即使看到那个单词,你依然不能断定到底这里面是用了单词的哪个解释;又或者想用一个词的时候,想不起那个词来。一些人原本英语很烂,但出国多年后英语照样杠杠的,我觉得在实际的语境中学语言是最好的,编程也一样!
在群友的追问下,得知这道题的来源..
这个题目是金山的笔试题
编译下面的代码 (左侧的数字是行号, 并非代码的一部分, 文件名为 hello.cpp)
1 #include <vector>
2
3 struct Point {
4 Point(int xx, int yy)
5 : x(xx)
6 , y(yy)
7 {}
8
9 int const x;
10 int const y;
11 };
12
13 int main()
14 {
15 std::vector<Point> pts;
16 pts.push_back(Point(0, 0));
17 return 0;
18 }
会产生类似下面的编译错误
hello.cpp: In member function ‘Point& Point::operator=(const Point&)’:
hello.cpp:3:14:
instantiated from `
void std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::iterator,
const _Tp&)
[with
_Tp = Point,
_Alloc = std::allocator<Point>
]'
/usr/include/.../stl_vector.h:??:??:
instantiated from `void std::vector<_Tp, _Alloc>::push_back(const value_type&)
[with
_Tp = Point,
_Alloc = std::allocator<Point>,
value_type = Point
]'
hello.cpp:16:30: instantiated from here
hello.cpp:3:14: error: non-static const member `const int Point::x',
can't use default assignment operator
hello.cpp:3:14: error: non-static const member `const int Point::y',
can't use default assignment operator
In file included from /usr/include/...ector:??:??,
from hello.cpp:1:
/usr/include/...ector.tcc: In member function `
void std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::iterator,
const _Tp&)
[with
_Tp = Point,
_Alloc = std::allocator<Point>
]':
/usr/include/...ector.tcc:??:??: note: synthesized method
`Point& Point::operator=(const Point&)' first required here
请问, 编译错误要表达什么信息? 你会如何修改上述代码以编译通过, 同时保持相近的代码意义?