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

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

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


1. 引用

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

   区别:

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

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

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

image

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

捕获

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

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

   (1)按值传递

    (2)引用传递

     (3)指针传递

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

  

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

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

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

2 c++ 内存管理

  内存分配方式

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

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

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

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

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

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

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

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

示例代码:

  

指针的内存的传递

复制代码
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维

  2维

  3维

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

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

   扩大

  缩小

  

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 @   wtx  阅读(630)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示