C/C++ 的一些乱七八糟的总结(一)

0.最近在复习C++,好多东西都忘了 ==!! 

从博客中,书中看到的一些东西,在这里简单总结下,没有章法,看到哪,复习到哪


1. 引用

  C++中引用 具备了 指针的 所有功能

   区别:

  (1) 引用在定义时必须初始化.引用和变量共享同一块内存空间,而指针单独有内存空间

   (2) 指针进行删除后,一般需要将其指向NULL,防止野指针,而引用至始而终都是它初始化时的地址,而且也不用删除,它会在作用域范围外由系统回收

 引用和它引用的变量指向的是同一块内存空间                                

image

   当修改其中任意一个值时,两个值都改变,当对引用重新赋一个新值时,引用的值和原来引用指向的值都改变为这个新值,而引用地址不变

捕获

在C ++ 中还可以定义一个类的对象的引用,与对象共享一块内存

     C++中 3  种传递函数参数的方式

   (1)按值传递

    (2)引用传递

     (3)指针传递

3种方式的示例代码如下:

#include <iostream>

using namespace std;

void f(int a)
{
    a = 10;
    cout << "函数f()中 a = " << a << endl;
}
void g(int * a)
{
    *a = 15;
    cout << "函数g() 中 a = " << *a << endl;
}
void h(int &a)
{
    a = 20;
    cout << "函数h() 中 a  = " << a << endl;
}
int main()
{
    int a = 1;
    cout << "按值传递前 a = " << a << endl;
    f(a);
    cout << "按值传递后 a = " << a << endl;
    cout << "按地址传递前 a  = " << a << endl;

    g(&a);
    cout << "按地址传递后 a = " << a << endl;
    cout << "按引用传递前 a = "  << a << endl;
    h(a);
    cout << "按引用传递后 a = " << a << endl;

    return 0;
}

  

可以看到按值传递,函数f()是不能修改a的

因为按值传递,只是把主函数a的值给了f函数的a值,这两个a的地址不是同一个地址,

在执行的过程中,会把主函数a的地址的数据拷贝给set函数a的地址

2 c++ 内存管理

  内存分配方式

   1. 从静态区分配,一般是全局变量和static类型变量

   2.从栈区分配内存,一般是局部的变量,会随着所在函数的结束而自动释放

   3.从堆中分配,一般是使用手动分配,使用malloc()函数和new来申请任意大小空间,不过要手动释放空间,相应的使用free()函数和delete释放,

    如果不释放该空间,而且指向该空间的指针指向了别的空间.则该空间就无法释放,造成内存泄露,造成了内存浪费

动态内存释放问题与野指针

当我们使用free()和delete释放一块内存时,指针还是指向原来的地址,不过这时候的指针时野指针

1.指针销毁了,并不表示所指的空间也得到了释放 :内存泄露

2.内存被释放了,并不表示指针也被销毁了或指向NULL :野指针

示例代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

int main()
{
    char *p = (char *)malloc(100);
    memset(p,0,10);//一般申请内存后,最好使用memset初始化一下
    strcpy(p,"hello world!");
    if(p)
    {
        cout << "p:" << p << endl;
    }

    free(p);
    // 所谓的野指针
    cout << "p:" << p << endl;
    if(p != NULL)
    {
        cout << "p不为空!" << endl;
    }
    p = NULL;


    return 0;
}

  

指针的内存的传递

View Code
#include <iostream>
#include
<stdlib.h>
#include
<string.h>
using namespace std;

// 返回内存地址方式,这是正确的 !
//因为是动态内存分配,在堆上分配的
char * getMemory()
{
char *p = NULL;
p
= (char *)malloc(sizeof(char));
memset(p,
0,sizeof(char));
return p;
}
//常见错误是在栈上分配的被返回了,错误的
char *getMemory2()
{
char p [] = "hello world";
return p;
}
//通过指针的指针方式申请内存
void getMemory3(char ** p)
{
*p = NULL;
*p = (char *)malloc(sizeof(char));
if(*p)
{
cout
<< "p:" << p << endl;
}
}


int main()
{
char *p1 = NULL;
char *p2 = NULL;
char *p3 = NULL;

p1
= getMemory();
if(p1)
{
cout
<< "p1申请成功!" << endl;
}

p2
= getMemory2();
if(p2)
{
cout
<< "p2申请成功!" << endl;
cout
<< "p2:" << p2 << endl;
}


getMemory3(
&p3);
if(p3)
{
cout
<< "p3申请成功!" << endl;
}
return 0;
}

3 动态数组(从csdn还是cnblogs中看到的,直接在这贴吧,网址找不到了)

  1维

#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1,i;
int *array;
printf("请输入所要创建的一维动态数组的长度:");
scanf("%d",&n1);
array=(int*)calloc(n1,sizeof(int));
for(i=0;i<n1;i++)
{
 printf("%d\t",array[i]);
}
printf("\n");
for(i=0;i<n1;i++)
{
 array[i]=i+1;
 printf("%d\t",array[i]);
}
 free(array);//释放第一维指针
return 0;
}

  2维

#include <stdio.h>
#include <stdlib.h>
int main()
{
int n1,n2;
int **array,i,j;
printf("请输入所要创建的动态数组的第一维长度:");
scanf("%d",&n1);
printf("请输入所要创建的动态数组的第二维长度:");
scanf("%d",&n2);
array=(int**)malloc(n1*sizeof(int*)); //第一维
for(i=0;i<n1; i++)
{
array[i]=(int*)malloc(n2* sizeof(int));//第二维
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
array[i][j]=i*n2+j+1;
printf("%d\t",array[i][j]);
}
printf("\n");
}
for(i=0;i<n1;i++)
{
free(array[i]);//释放第二维指针
}
free(array);//释放第一维指针
return 0;
}

  3维

#include <stdlib.h>
#include <stdio.h>
int main()
{
int n1,n2,n3;
int ***array;
int i,j,k;
printf("请输入所要创建的动态数组的第一维长度:");
scanf("%d",&n1);
printf("请输入所要创建的动态数组的第二维长度:");
scanf("%d",&n2);
printf("请输入所要创建的动态数组的第三维长度:");
scanf("%d",&n3);
array=(int***)malloc(n1*sizeof(int**));//第一维
for(i=0; i<n1; i++)
{
array[i]=(int**)malloc(n2*sizeof(int*)); //第二维
for(j=0;j<n2;j++)
{
array[i][j]=(int*)malloc(n3*sizeof(int)); //第三维
}
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
for(k=0;k<n3;k++)
{
array[i][j][k]=i+j+k+1;
printf("%d\t",array[i][j][k]);
}
printf("\n");
}
printf("\n");
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++)
{
free(array[i][j]);//释放第三维指针
}
}
for(i=0;i<n1;i++)
{
free(array[i]);//释放第二维指针
}
free(array);//释放第一维指针
return 0;
}

  更多的维度也能照此写出来

   使用recolloc进行数组的扩大或者缩小:

   扩大

#include <stdio.h>
#include <stdlib.h>
int main()
{
int*n,*p;
int i,n1,n2;
printf("请输入所要创建的动态数组的长度:");
scanf("%d",&n1);
n=(int*)calloc(n1,sizeof(int));
printf("请输入所要扩展的动态数组的长度:");
scanf("%d",&n2);
p=(int*)realloc(n,(n2)*sizeof(int));//动态扩充数组
for(i=0;i<n2;i++)
{
p[i]=i+1;
if(i%5==0)
printf("\n");
printf("%d\t",p[i]);
}
free(p);
return 0;
}

  缩小

#include <stdio.h>
#include <stdlib.h>
int main()
{
int*n,*p;
int i,n1,n2;
printf("请输入所要创建的动态数组的长度:");
scanf("%d",&n1);
n=(int*)calloc(n1,sizeof(int));
for(i=0;i<n1;i++)
{
n[i]=i+1;
if(i%5==0)
printf("\n");
printf("%d\t",n[i]);
}
printf("\n请输入所要缩小的动态数组的长度:");
scanf("%d",&n2);
p=(int*)realloc(n,(n2)*sizeof(int));
for(i=0;i<n2;i++)
{
if(i%5==0)
printf("\n");
printf("%d\t",p[i]);
}
printf("\n");
free(p);
return 0;
}

  

4.  sizeof()

   

#include <iostream>
#include <stdio.h>
using namespace std;
 //linux内核链表里的一个宏
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)4)->MEMBER)


typedef struct stu1
{
    int a;
    int b;
}stu1;
void print()
{
    cout << "hello world" << endl;
}
int print2()
{
    cout << "hello world" << endl;
    return  1;
}




#pragma pack (1) /*指定按1字节对齐*/

typedef union stu
{
	char str[10];
	int b;
}stu;

#pragma pack () /*取消指定对齐,恢复缺省对齐*/

typedef union stu2
{
	char str[10];
	int b;
}stu2;




int main()
{
    int i;
    //sizeof可以对一个表达式求值,编译器根据表达式的最终结果确定大小
    //但是不会对表达式进行计算,不会对函数进行执行
	printf("sizeof(i):\t%d\n",sizeof(i));
	printf("sizeof(4):\t%d\n",sizeof(4));
	printf("sizeof(4+2.5):\t%d\n",sizeof(4+2.5));
	printf("sizeof(int):\t%d\n",sizeof(int));
	printf("sizeof 5:\t%d\n",sizeof 5);

	cout << "============================" << endl;
    //对于void类型,其长度为1
    cout << sizeof(print()) << endl;
  //int型的返回值,其长度为4(都是在32位机器)
    cout << sizeof(print2()) << endl;



    cout << "============================" << endl;
    printf("offsetof(stu1,a):%d\n",offsetof(stu1,a)-4);
    cout << "ofsetof(stu1,a):" << offsetof(stu1,a) - 4 << endl;
    printf("offsetof(stu1,b):%d\n",offsetof(stu1,b)-4);



    cout << "============================" << endl;
     printf("sizeof(stu)    :\t%d\n",sizeof(stu));
    printf("sizeof(stu2)    :\t%d\n",sizeof(stu2));


    return 0;
}

  对于结构体:

#include <stdio.h>

typedef struct stu1
{
	char array[7];
}stu1;

typedef struct stu2
{
	double fa;
}stu2;

typedef struct stu3
{
	stu1 s;
	char str;
}stu3;

typedef struct stu4
{
	stu2 s;
	char str;
}stu4;

typedef struct stu5
{
    double d1;
    int i1;
    char c1;
}stu5;

typedef union stu6
{
    double d1;
    int i1;
     char c1;
}stu6;

typedef struct stu7
{
    char c1;
    int i1;
    double d1;
}stu7;

typedef struct stu8
{
    int i1;
    char c1;
    double d1;
}stu8;


int main()
{
	printf("sizeof(stu1)    :\t%d\n",sizeof(stu1));
	printf("sizeof(stu2)    :\t%d\n",sizeof(stu2));
	printf("sizeof(stu3)    :\t%d\n",sizeof(stu3));
	printf("sizeof(stu4)    :\t%d\n",sizeof(stu4));
	printf("sizeof(stu5)    :\t%d\n",sizeof(stu5));
	printf("sizeof(stu6)    :\t%d\n",sizeof(stu6));
	printf("sizeof(stu7)    :\t%d\n",sizeof(stu7));
	printf("sizeof(stu8)    :\t%d\n",sizeof(stu8));
	return 0;
}

  size_t ,对于大小的比较,或者其他计算,会变成其补码形式

#include <iostream>

using namespace std;

int main()
{
    size_t a = -1;
    size_t b = 10;
    if(a<b)
    cout << "a < b" << endl;
    else
    cout << "a !< b" << endl;
    return 0;
}

  答案是 a !< b


5 一道堆栈指针问题

#include <iostream>

using namespace std;

//指针的地址是在栈中(首地址除外),但是指针指向的内容却在堆中,
//所以并没有被清除

char* get_str()
{
    char* str = {"abcd"};
     return str;
}
//栈里面的变量都是临时的。当前函数执行完成时,
//相关的临时变量和参数都被清除了,所以返回的指针指向的已经是随机的了
//但是str[]首地址被当成指针来处理,存放在堆中。
char* get_str2()
{
    char str[] = {"abcd"};
     return str;
}
int main(int argc, char* argv[])
{
    char* p = get_str();
    cout << *p << endl;
    cout << *(p+1) << endl;
    cout << p << endl;
    cout << "========================" << endl;

    char *p2 = get_str2();
    //第1次执行 *p2的时候,由于p2指针的首地址被返回了,还是可以取到*p2的内容的
    /*
      可以试试取*(p2+1),也是可以取到的
    */
    cout << *p2 << endl;
   
    //第一次调用*p2的时候还是有数据的,但是第2次就没有了,
    //说明cout之后指针已经被破坏了
    cout << *p2 << endl;
    cout << *(p2+1) <<endl;
    cout << *p2 << endl;
    cout << p2 << endl;
     return 0;
}

  

  参考:整理自互联网

http://blog.csdn.net/bizhu12/article/details/6668834

http://blog.csdn.net/bizhu12/article/details/6666176

http://blog.csdn.net/bigloomy/article/category/840249

posted @ 2011-08-13 21:48  wtx  阅读(628)  评论(0编辑  收藏  举报