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)  
可以看出两个函数都没有被处理成内联函数!!!!!

0 0