C++笔记——动态内存分配

new/delete【C++动态分配运算符,可以重载】、malloc/free【C语言动态分配函数,不能重载】需要配对使用。

new [] / delete [] 生成和释放对象数组。

#include <iostream>
#include <stdlib.h>

using namespace::std;

class Test{
public:
    Test()
        : m_val(0)
    {
        cout << "Test" << endl;
    }
    ~Test(){
        cout << "~Test" << endl;
    }
private:
    int m_val;
};

int main()
{
    {
        Test a;
    }
    cout << "end of }" << endl;

    Test* pVal = new Test();
    delete pVal;
    pVal = NULL;

    int* p = (int *)malloc(sizeof(int));
    free(p);
    p = NULL;

    Test* pArray = new Test[2]; // 调用两次构造函数
    delete[] pArray;            // 调用两次析构函数

    return 0;
}

-----------------------------------------------------------------

Bss段存放没有初始化或者初始化为0的全局变量。

Data段存放初始化为非零的全局变量。

静态变量在第一次进入作用域时被初始化,以后不必再初始化。

静态成员变量在类之间共享数据,也是放在全局/静态数据区中。并且只有一份拷贝。

#include <iostream>
#include <stdio.h>

int i = 0;

class A
{
public:
    int val;
    static int nCount;
    A() {++nCount;}
    ~A() {--nCount;}
};

int A::nCount = 0; // 初始化类的静态成员变量

int main()
{
    A a;
    A b;

    printf("Number of A is %d ===>\n\n", A::nCount);
    printf("no static variable: 0x%x\n", &a.val);
    printf("no static variable: 0x%x\n", &b.val);
    printf("static class member: 0x%x\n", &a.nCount); 
    printf("static class member: 0x%x\n", &b.nCount);
    printf("global member: 0x%x\n", &i);

    return 0;
}


-----------------------------------------------------------------

rodata存放常量数据。

常量不一定挡在rodata中,有些立即数直接和指令编码在一起,放在text中。

字符串常量,编译器会去掉重复的字符串,保证只有一个副本。

字符串会被编译器自动放到rodata中,加const关键字修饰的全局变量也放在rodata中

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>

int main()
{
    char* p = "Hello";
    char* p2 = "Hello";
    // 字符串常量,编译器会去掉重复的字符串,保证只有一个副本
    printf("p指向地址 = %p\n", p);
    printf("p2指向地址 = %p\n", p2);
    if(p == p2)
    {
        printf("Smart complier, set the string in one place!\n");
    }

    char* p3 = (char*)malloc(12);
    memset(p3, 0, 12);   // ACSII码是0表示空格
    // 将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值,
    // 第一个值为指定的内存地址,块的大小由第三个参数指定,
    // 这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针。
    printf("p3 = %s\n", p3);
    printf("p3指向地址 = %p\n", p3);
    strcpy(p3, p2);
    printf("p3 = %s\n", p3);
    p3[1] = 'x';
    printf("p3 = %s\n", p3);
    free(p3);
    p3 = NULL;

    // p[1] = 'x';  会出现段错误,常量字符串是不能修改的

    return 0;
}

栈中存储自动变量或局部变量,以及传递的参数等。

堆是用户程序控制的存储区,存储动态产生的数据。

当用malloc/new来申请一块内存或者创建一个对象时,申请的内存在堆上分配,需要记录得到的地址,并且在不需要的时候释放这些内存。

栈一般很小,满足不了程序逻辑的要求。

-----------------------------------------------------------------

#include <iostream>
#include <stdio.h>

class AA{
public:
    A() {printf("A created\n");}
    ~A() {printf("A destroyed\n");}
};

class B{
public:
    B() {printf("B created\n");}
    ~B() {printf("B destroyed\n");}
};

A globalA; // 调用A的构造函数
B globalB; // 调用B的构造函数

int foo(void)
{
    printf("\nfoo()---------------->\n");
    A localA; // 调用A的构造函数
    static B localB; // 调用B的构造函数,因为localB是静态对象,不用再次调用构造函数
    printf("foo()<-------------------\n");
    return 0;  // 至此只调用A的析构函数,静态对象localB生命期未到。
}

int main()
{
    printf("main()------------------->\n");
    foo();
    foo();
    printf("main()<-------------------\n");
    return 0;
    // 至此分别调用B和A的析构函数2次和1次
}


作用域由{}定义,并不一定是整个函数。

------------------------------------------------------------------------------------------

#include <iostream>
#include <stdio.h>

class A{
public:
    A() {printf("A created\n");}
    ~A() {printf("A destroyed\n");}
    // 拷贝构造函数
    A(const A& a) {printf("A created with a copy\n");}
};

A *foo(A a)
{
    printf("\nfoo()---------------->\n");
    A *p = new A();  // 调用A的构造函数
    printf("foo()<-------------------\n");
    return p;      // 调用A的析构函数(对应32行的拷贝构造函数)
}

A *boo(const A& a)
{
    printf("\nboo()---------------->\n");
    A *p = new A();  // 调用A的构造函数
    printf("boo()<-------------------\n");
    return p;
}

int main()
{
    printf("main()---------------->\n");
    A a;  // 调用A的构造函数
    A *p = foo(a); // 传递a的副本,调用A的拷贝构造函数
    delete p;     // 调用A的析构函数(对应15行的构造函数)
    p = NULL;

    p = boo(a); // 传递a的引用
    delete p;   // 调用A的析构函数(对应23行)
    p = NULL;
    printf("main()<----------------\n");
    // // 调用A的析构函数(对应31行的构造函数)
    return 0;
}




#include <iostream>
#include <stdio.h>

class A{
public:
    A() {printf("A created\n");}
    ~A() {printf("A destroyed\n");}
};

A *CreateA(void)
{
    printf("\nCreateA()---------------->\n");
    A *p = new A();  // 调用A的构造函数
    printf("\nCreateA()<----------------\n");
    return p;
}

int main()
{
    A *pA = new A(); // 调用A的构造函数
    printf("pA = 0x%x\n", pA);
    delete pA;       // 调用A的析构函数

    pA = CreateA();
    printf("pA = 0x%x\n", pA);
    delete pA;       // 调用A的析构函数

    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值