c++备忘录2
来源:互联网 发布:为什么建设网络强国 编辑:程序博客网 时间:2024/05/16 08:12
1.操作符重载,总结一下,个人觉得只有三种情况:
情形a: 在类内部重载操作符
class base{public:base(int x){a = x;}base & operator+(base &obj1);void get_number(){cout << a << endl;}private:int a;};base & base::operator + (base &obj1){this->a += obj1.a;return *this;}int main(){base b1(1);base b2(2);b1 + b2;b1.get_number();return 0;}
情形2:在外部重载:
class base{public:base(int x){a = x;}void get_number(){cout << a << endl;}int a;};base & operator + (base &obj1,base &obj2){obj1.a+= obj1.a;return *(&obj1);}
情形3:友元重载
class base{public:base(int x){a = x;}void get_number(){cout << a << endl;}friend base &operator+(base &obj1,base &obj2);private:int a;};base & operator + (base &obj1,base &obj2){obj1.a+= obj1.a;return *(&obj1);}
2.c++让人眩晕的指针
1.int(**ptr)[10];//下面有讨论2.int*(*ptr)[10];//如果写成int(*ptr)[10]大家都知道,ptr是一个指向有10个元素的素组每个元素是int型,//那么类比,int*(*ptr)[10]中ptr也是指向含有10个元素的数组,但是数组中的每个元素是int *型的3.int(*f[10])(int);//函数指针数组,f的每个元素都指向参数为int型,返回int值的函数4.int *((*ptr)[10]);//和第二种情况一样
在弄清楚之前我们要知道下面的几个指针
int *ptr:这个指针指向的是一个int型对象,如果ptr++则跳到下一个int型对象的地址;
int (*ptr)[10]:这是一个一维数组指针,ptr++会跳过10个int型对象;
当数组名作为函数参数的时候,编译器自动将其转化成int *的变量;
#include<iostream>#include<vector>#include<list>#include<fstream>#include<string>#include<set>#include<map>#include<algorithm>#include<stack>using namespace std;#define size 10int func(int ar[]){cout << typeid(ar).name()<< endl;return 0;}int main(){int (*p)[10];int arr[10];for (int j = 0; j < size;j++){arr[j] = rand() % 100;}p = &arr;//可以看到arr的类型为int [10],在&运算符后就变成int(*)[10]cout << typeid(&arr).name() << endl;int(**ptr)[10] = &p;cout << *(**ptr+1) << endl;//ptr存放的是p变量的地址,*ptr(和p的值一样)就指向了含有10个元素的数组的地址,此时是行地址//**ptr将行地址转换成列地址,**ptr+1就是数组中第一个元素的地址,*(**ptr+1)就是第一个元素的值//如有不懂,参考我的另外一篇博客:http://blog.csdn.net/caoyan_12727/article/details/52549075cout << *((int *)p+1) << endl;func(arr);return 0;}输出:
3.定义变长结构体
struct node{int a;int arr[0];//不为arr分配空间};int main(){cout << sizeof(node) << endl;struct node * ptr = (struct node *)malloc(20 * sizeof(char));//ptr指向20字节的空间 for (int i = 0; i < 5; i++){*((int *)ptr + i) = rand() % 20;cout << *((int *)ptr + i) << endl;}cout << ptr->a << endl;return 0;}
4.使用变长参数:
代码:
int sum(int num,...){int sum=0;va_list ap;va_start(ap,num);for (int i = 0; i < num; i++){sum += va_arg(ap, int);}va_end(ap);<span style="white-space:pre"></span>return sum;}int main(){int a = 1;int b = 2;int c = 3;int d = 4;int re = sum(4,a,b,c,d);cout << re << endl;//re正确输出10return 0;}边长参数的实现依赖于下面5个宏:
1)typedef char * va_list;2)_INTSIZEOF 宏,获取类型占用的空间长度,最小占用长度为int的整数倍:#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )3)VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数):#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )4)VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型):#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )5)VA_END宏,清空va_list可变参数列表:#define va_end(ap) ( ap = (va_list)0 )
5.malloc(0)的特殊情况:
<pre name="code" class="cpp">int main(){char* ptr = (char *)malloc(0 * sizeof(char));if (NULL == ptr)printf("got a null pointer\n");else printf("got a valid pointer\n");printf("%p\n", ptr);free(ptr);cout << sizeof(ptr) << endl;printf("0x%01x\n", *ptr);bitset<8>bit(*ptr);cout << "bit:"<<bit << endl;cout << "*ptr:"<<*ptr << endl;//另外测试:char ch = 'a';char *ptr1 = &ch;bitset<8>bit1(*ptr1);cout << bit1 << endl;return 0;}输出:
这个目前没搞懂,希望高人指点!!!!!
6.指针和数组在函数调用的时候的传递
#include<iostream>using namespace std;void func(int a,char arr[],char *p){cout<<"here!"<<endl;}int main(){int a=10;char s[]="aaaaaaaaaaaaaaaaaaaaaaaaa";char *p="bbbbbbbbbb";func(a,s,p);return 0;}
汇编码:
0804872a <main>: 804872a:8d 4c 24 04 lea 0x4(%esp),%ecx 804872e:83 e4 f0 and $0xfffffff0,%esp 8048731:ff 71 fc pushl -0x4(%ecx) 8048734:55 push %ebp 8048735:89 e5 mov %esp,%ebp 8048737:51 push %ecx 8048738:83 ec 34 sub $0x34,%esp 804873b:65 a1 14 00 00 00 mov %gs:0x14,%eax 8048741:89 45 f4 mov %eax,-0xc(%ebp) 8048744:31 c0 xor %eax,%eax 8048746:c7 45 d0 0a 00 00 00 movl $0xa,-0x30(%ebp) 804874d:c7 45 da 61 61 61 61 movl $0x61616161,-0x26(%ebp) 8048754:c7 45 de 61 61 61 61 movl $0x61616161,-0x22(%ebp) 804875b:c7 45 e2 61 61 61 61 movl $0x61616161,-0x1e(%ebp) 8048762:c7 45 e6 61 61 61 61 movl $0x61616161,-0x1a(%ebp) 8048769:c7 45 ea 61 61 61 61 movl $0x61616161,-0x16(%ebp) 8048770:c7 45 ee 61 61 61 61 movl $0x61616161,-0x12(%ebp) 8048777:66 c7 45 f2 61 00 movw $0x61,-0xe(%ebp) 804877d:c7 45 d4 a6 88 04 08 movl $0x80488a6,-0x2c(%ebp) 8048784:83 ec 04 sub $0x4,%esp 8048787:ff 75 d4 pushl -0x2c(%ebp) 804878a:8d 45 da lea -0x26(%ebp),%eax 804878d:50 push %eax 804878e:ff 75 d0 pushl -0x30(%ebp) 8048791:e8 65 ff ff ff call 80486fb <_Z4funciPcS_> 8048796:83 c4 10 add $0x10,%esp 8048799:b8 00 00 00 00 mov $0x0,%eax 804879e:8b 55 f4 mov -0xc(%ebp),%edx 80487a1:65 33 15 14 00 00 00 xor %gs:0x14,%edx 80487a8:74 05 je 80487af <main+0x85> 80487aa:e8 11 fe ff ff call 80485c0 <__stack_chk_fail@plt> 80487af:8b 4d fc mov -0x4(%ebp),%ecx 80487b2:c9 leave 80487b3:8d 61 fc lea -0x4(%ecx),%esp 80487b6:c3 ret我们可以看到:
(1)对于普通变量a是是将它的地址入栈
pushl -0x30(%ebp)
(2)对于数组,也是将它的地址入栈
804878a:8d 45 da lea -0x26(%ebp),%eax 804878d:50 push %eax(3)对于指针变量:
8048787:ff 75 d4 pushl -0x2c(%ebp)也是将它的地址入栈
在这里我们要注意两个串,一个是"aaaaaaaaa"和"bbbbbbbbbbbb",前者对数组进行赋值,后者是将其存放在.rodata段,而将其地址赋值给变量p;
7.内联函数与虚函数之间的关系
1.内联函数是个静态行为,而虚函数是个动态行为,他们之间是有矛盾的。
2.我们之所以能看到一些象内联函数的虚函数,是因为某个函数是否是内联函数不是由我们说的算,而是由编译器决定的。我们只能向编译器建议,某个函数可以是内联函数(inline关键字),但是编译器有自己的判断法则。所以可能出现这样的情况:
2.1 我们用inline声明的函数却没有inline
2.2 我们没有用inline声明的函数却是inline
2.3 对于inline函数,编译器仍然将它编译成一个有地址的函数
所以,情况比较复杂,从high-level来看的话很难判断函数是否是inline的,如果从low-level来看的话就比较清晰,非内联函数遵从函数调用机制,在汇编中用call来调用。内联函数则没有这些。
class base{public:inline ~base(){cout << "a inline virtual function!"<< endl;}virtual inline int func(int x,int y){return x + y;}int a;};inline int func1(int x, int y){return x + y;}int main(){base bb;cout << bb.func(2, 3) << endl;cout <<func1(2, 3) << endl;return 0;}再来看看汇编码:
cout << bb.func(2, 3) << endl;009B649F mov esi,esp 009B64A1 push 9B13E3h 009B64A6 push 3 009B64A8 push 2 009B64AA lea ecx,[bb] 009B64AD call base::func (09B14E7h)
cout <<func1(2, 3) << endl;009B64D7 mov esi,esp 009B64D9 push 9B13E3h 009B64DE push 3 009B64E0 push 2 009B64E2 call func1 (09B14ECh)可以看出两个函数都没有被处理成内联函数!!!!!
- 备忘录(C语言)
- 备忘录 C/C++
- 【C++】Chapter14:备忘录模式
- C语言程序备忘录
- C/C++ 学习备忘录
- Objective C--备忘录模式
- Objective C 备忘录模式
- 备忘录--C语言
- 备忘录 C/C++
- C学习备忘录
- C的IO备忘录
- C语言设计模式:备忘录
- 【C++Primer备忘录】 习题10.25
- UE4(C++) 初学备忘录
- 我的C/C++备忘录
- 【备忘录-c/c++】typedef的使用总结
- YetAnotherForum备忘录2
- shell初级教程-备忘录2
- Effective Java
- 新的开始。。。
- 最长公共子序列VS最长连续公共子序列
- 浅析 - TabLayout的基本用法
- BGRABitmap图像操作13:BGRABitmap的坐标系统
- c++备忘录2
- IntelliJ Idea 常用快捷键列表
- 98. Validate Binary Search Tree(中序遍历判断BST)
- 理解本真的REST架构风格
- 中国剩余定理(模板+代码)
- 文本格式化标签
- 跟我一起写 Makefile(一)
- Bootstrap-maxlength使用
- Xcode中的Info.plist字段列表详解