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;
}
指针的内存的传递

C/C++ 的一些乱七八糟的总结(一)C/C++ 的一些乱七八糟的总结(一)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("%dt",array[i]);
}
printf("n");
for(i=0;i<n1;i++)
{
 array[i]=i+1;
 printf("%dt",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("%dt",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("%dt",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("%dt",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("%dt",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("%dt",p[i]);
}
printf("n");
free(p);
return 0;
}
  1. 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%dn",sizeof(i));
    printf("sizeof(4):t%dn",sizeof(4));
    printf("sizeof(4+2.5):t%dn",sizeof(4+2.5));
    printf("sizeof(int):t%dn",sizeof(int));
    printf("sizeof 5:t%dn",sizeof 5);

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



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



    cout << "============================" << endl;
     printf("sizeof(stu)    :t%dn",sizeof(stu));
    printf("sizeof(stu2)    :t%dn",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%dn",sizeof(stu1));
    printf("sizeof(stu2)    :t%dn",sizeof(stu2));
    printf("sizeof(stu3)    :t%dn",sizeof(stu3));
    printf("sizeof(stu4)    :t%dn",sizeof(stu4));
    printf("sizeof(stu5)    :t%dn",sizeof(stu5));
    printf("sizeof(stu6)    :t%dn",sizeof(stu6));
    printf("sizeof(stu7)    :t%dn",sizeof(stu7));
    printf("sizeof(stu8)    :t%dn",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
原文链接: https://www.cnblogs.com/hitwtx/archive/2011/08/13/2137562.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/30450

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午7:46
下一篇 2023年2月8日 上午7:47

相关推荐