C++核心DAY1

内存分区

C++将内存分为四个区域 代码区 全局区 堆区 栈区

代码区是共享的 为什么共享? 比如说一个exe程序要被多次执行,你点一次执行一次,所以不是每点一次在代码区生成这个代码,而是一直调用代码区的同一块代码。

代码区是只读的, 防止程序意外修改

全局区存放 全局变量 静态变量 字符串常量也在
栈区存放 局部变量 局部常量

int g_a=10,g_b=100;
const int c_a=10,c_b=100;
int main()
{
    int a=10; int b=100; //局部变量
    cout<<"局部变量a的地址为"<<(long long)&a<<"  局部变量b的地址为="<<(long long)&b<<endl;
    const int j_a=10,j_b=100;
    cout<<"局部常量j_a的地址为"<<(long long)&j_b<<"  局部常量j_b的地址为="<<(long long)&j_b<<endl;
    cout<<"全局变量g_a的地址为"<<(long long)&g_a<<"  全局变量g_b的地址为="<<(long long)&g_b<<endl;
    cout<<"字符串常量地址为"<<(long long)&"hello world"<<endl;
    static int s_a=10;
    static int s_b=100;
    cout<<"静态变量s_a的地址为"<<(long long)&s_a<<"  静态变量s_b的地址为="<<(long long)&s_b<<endl;
    cout<<"全局常量c_a的地址为"<<(long long)&c_a<<"  全局变量c_b的地址为="<<(long long)&c_b<<endl;
}

image-tqvy.png

这段代码执行不通,a定义在函数内部,生成在栈区,test执行完成之后栈区的东西自动释放

int* test()
{
    int a=10;
    return &a;
}
int main()
{
    int *p=test();
    cout<<*p<<endl;
    cout<<*p<<endl;
    system("pause");
    return 0;
}

这段代码可以执行,因为函数test使用了new,new生成的空间在堆区,由程序员决定是否释放,释放使用delete,或在程序执行完成之后自动释放

int* test()
{
    int *a=new int(10);
    return a;
}
int main()
{
    int *p=test();
    cout<<*p<<endl;
    cout<<*p<<endl;
    system("pause");
    return 0;
}

image-akqr.png

引用

int main()
{
   int a=10;
   int &b=a;  
   cout<<a<<endl;  
   cout<<b<<endl;
   b=100;
   cout<<a<<endl;
   cout<<b<<endl
    system("pause");
    return 0;
}

image-dugw.png

引用必须初始话指的是 int &b之后必须要要有个 = 指向一边 直接int &b;是错误的

引用在初始化之后不能更改是指,int &b=a之后;你不能b=c,让b指向c的地址;b=c是赋值操作,将c的值传递给b

值传递是形参实参问题,在main函数内是实参,在swap1内是形参,在栈区生成了一组新的a和b

地址传递 将a和b的地址传入进swap2函数,所以在main函数中调用时,要使用&,取地址符

在swap2函数头写*解引用, *a这个符号意味着获取a这个指针指向地址的值

swap3是医用传递,简单的就是可以不用在main函数中写&

//值传递
void swap1(int a,int b)
{
    int t=a;
    a=b;
    b=t;
}
//地址传递
void swap2(int *a,int *b)
{
    int t=*a;
    *a=*b;
    *b=t;
}
//引用传递
void swap3(int &a,int &b)
{
    int t=a;
    a=b;
    b=t;
}
int main()
{
    int a=1,b=2;
    swap1(a,b);
    cout<<a<<"  "<<b<<endl;
    swap2(&a,&b);
    cout<<a<<"  "<<b<<endl;
    a=1,b=2;
    swap3(a,b);
    cout<<a<<"  "<<b<<endl;


    system("pause");
    return 0;
}

image-edet.png

这段调用test无法执行,因为a是生成在栈区,函数自动释放

test2可执行因为 静态变量生成在全局区

int& test()
{
    int a=10;
    return a;
}


int& test2()
{
    static int a=10;
    return a;
}

int main()
{
   int &t=test2();
    cout<<t<<endl;

    system("pause");
    return 0;
}

引用的本质

引用的本质其实就是一个指针常量,指向一个地址例如

int a=10;
int &b=a;
b=1000;

现在b就是一个指向a地址的指针 int* const b=a; b=1000,本质上是*b=1000,但是编译器帮我们省略了这个过程

函数

函数的形参可以有默认值。注意事项:

  • 如下图如果1号形参有默认值,则2,3号形参也必须要有默认值;
    1号无,2号有,则3号也要有;
int sum(int a=10,int b=20,int c=30)
{
    return a+b+c;
}

  • 如果函数声明有默认值,则在函数实现时不能有默认值,因为如果实现的时候有默认值,则计算机不知道该调用哪个默认值。
int  sum(int a=10,int b=20,int c=30);
int sum(int a,int b,int c)
{
    return a+b+c;
}


函数的占位参数,(不知道哪来干嘛的),意思是可以可以放一个函数内完全不需要使用的数字进入形参,栈区?

void print(int a)
{
    cout<<"This is a test"<<endl;
}

函数的重载

这几种情况都可以发生重载,函数参数类型不同,个数不同,形参顺序不同

函数返回类型不能成为发生重载的条件

void test()
{
    cout<<"THIS IS A TEST"<<endl;
}
void test(int a)
{
    cout<<"THIS IS "<<a<<" TEST"<<endl;
}
void test(double a)
{
    cout<<"THIS IS "<<a<<" TEST"<<endl;
}
void test(int a,int b)
{
    cout<<"THIS IS "<<a<<" and "<<b<<" TEST"<<endl;
}

void test(int a,double b)
{
    cout<<"THIS IS "<<a<<" and "<<b<<" TEST"<<endl;
}
void test(double b,int a)
{
    cout<<"THIS IS "<<b<<" and "<<a<<" TEST"<<endl;
}