Amusing C++:运算符顺序和类的构造函数
来源:互联网 发布:sql 它代表什么 编辑:程序博客网 时间:2024/05/17 03:39
原文网址 http://www.codeguru.com/cpp/article.php/c19303/Amusing-C.htm
Q.: How many apples does Bart have?
A.: Who knows? We're still unaware of how many apples he had to start!Can C++ be funny? Let's check it out! Here are some examples that gladden the programmer's eye. Enjoy looking at them!
Let us start - and may the Source be with you! Suppose we have the following code:
int a = 5;int b = a++ + ++a;
What does b equal? Are you sure? :) The point is that the right value lies somewhere between 10 and 14! My GCC returns 12, but that's not the limit yet! The C++ Standard does not presuppose the calculation of the++ operator before the assignment operator is done - so that the answer may vary depending on the compiler; it may even depend on the optimization keys. Note that the result of the operationi = i++ is not defined either! People who want to learn more, can google "C++ sequence point", while we go on!
What do you think - is this code workable?
int i[i];int j = j;x x;int y::y = x.x;Strange as it may seem, it is - if we do like this:
const int i = 1;const int j = 2;struct x{ int x;};namespace y{ int i[i]; int j = j; x x; int y::y = x.x;};
Visibility overlap did its dirty deed! :) However, MSVC does not accept such code: it considers the declaration ofint x to be a declaration of the constructor (the latter, as is known, cannot return a value). And, what's even worse, the namespaced variable j will have an unexpected value, though it is "initialized". So, this clearly indicates that such "tricks" are not worth being played!
Let's go on with the next example. Here's another nice code I've gotten you into! :) This one marked the beginning of my collection of C++ pranks, and I like it the most. Apart from being a really cool prank, it also comprises a psychological trick. Just look at this:
T t1;T t2(t1);T t3 = t1;T t4();
Which constructor will be called in each of these four cases? If you have decided that those must be:
- default constructor,
- copy constructor,
- assignment operator, and
- default constructor again,
int func();
If you made no mistakes, congratulations! If you made one nevertheless and are now craving another chance to win, here's a new opportunity for you! Suppose you have this class:
class C {public: C() { printf("default\n"); } C(long) { printf("long\n"); } explicit C(int) { printf("int\n"); } C(const C&) { printf("copy\n"); } C &operator=(const C&) { printf("op=\n"); return *this; }};Also, you have a code that involves it:
void prn(int n){ cout << n << ": ";}int main(){ const int i = 0; prn(1); C c1(); prn(2); C c2 = i; prn(3); C c3(i); prn(4); C c4 = C(i); prn(5); C c5 = (C) i; prn(6); C c6 = static_cast(i); return 0;}What will be displayed on the screen then? To be honest, I made a mistake myself here. And that mistake was severe and reiterated :) So, please be extremely focused. Done? The right answer is:
1: 2: long3: int4: int5: int6: intNaturally, one is blank; as you remember, it is a function declaration. Two did not manage to build a class fromint, since the int-constructor is specified as explicit; however, the compiler obligingly convertedint into long - where its own constructor already exists. The rest of options are variations on a theme of C(i), although differently decorated. I cannot but admire the competence of the translator, which used neither excessive copy constructor, nor assignment constructor, nor even default constructor. C++ at its best!
Here's the last example - maybe the most "practical" among those cited. Suppose you need to create a cycle in which the value of a variable tends to zero. Certainly, you can use the operatorfor. But we can also do like this!
int i = 10;while (i --> 0){ cout << i << endl;}
This thingamajig is called "arrow operator", just in case.
Here were the tricks originating in our more-than-native language. And then, C++0x may well come, which conceals many such pranks, I guess. As for now, let's keep in mind that this code is nothing but a joke - it ain't a blueprint for action! :)
- Amusing C++:运算符顺序和类的构造函数
- 【C++】复制构造函数(拷贝构造函数)和=运算符重载使用的区别
- C++:类的复制构造函数、赋值运算符
- 类的构造函数、拷贝构造函数、赋值运算符和析构函数
- 类的构造函数和new运算符
- 类的赋值运算符重载和拷贝构造函数
- 派生类构造函数和析构函数的调用顺序(C++)
- [C++]拷贝构造函数和赋值运算符重载
- C++ 构造函数和运算符重载
- C++——转换构造函数和转换运算符
- c/c++ 构造函数、拷贝构造函数、析构函数和赋值运算符重载
- 构造函数访问权限和基类构造函数,派生类的构造函数调用顺序
- 总结c++类的构造函数 拷贝构造函数 析构函数 赋值运算符重载的特点以及函数调用顺序
- 【C++】基类和派生类构造函数的调用顺序
- c/c++中如何写结构体的 构造函数 和 重载运算符?
- 类的析构函数和构造函数调用顺序
- 【C++】探究类派生时构造函数的顺序
- 【c++】构造函数调用顺序的研究
- 利弊皆知 云操作系统OpenStack的能力
- 用户控件
- Find Original & JiFen
- oracle分割字符串函数
- 适用ADO与sql2008交互的一个例子
- Amusing C++:运算符顺序和类的构造函数
- C#基础:ref和out的区别
- SqlTableModel与QTableView
- replace()与replaceAll()的区别
- 在Linux下实现一个简单的命令 交互UI(类shell交互界面)
- gridview生成XMl文档
- 通过rowid值获得块号,文件号的函数
- 调试错误集1
- Android基础之菜单详解