【c++】动态内存

静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。注意:const常量在定义时必须初始化

栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放,栈区由系统自动分配。

堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。

shared_ptr类

shared_ptr初始化:使用make_shared<T>(args)函数

shared_ptr<int> p=make_shared<int>(42);

auto p=make_shared<string>();

每个shared_ptr都有一个关联的计数器(引用计数)即多少个指针指向shared_ptr管理的变量,无论何时我们拷贝一个shared_ptr,计数都会递增。当我们给shared_ptr赋予一个新值或是shared_ptr被销毁时,计数器就会递减。一旦一个shared_ptr的计数器变为0,就会自动释放自己管理的对象。

auto p=make_ptr<int>(42);//p指向的对象只有一个引用者

auto q(p);//p和q指向相同对象,此对象有两个引用者

auto r=make_shared<int>(42);

r=q;//r原来指向的对象已没有引用者,会自动释放

总结:智能指针类能记录有多少shared_ptr指向相同的对象,并能在恰当的时候自动释放对象。

直接管理内存

动态分配的对象是默认初始化的,这意味着内置类型或组合类型的对象的值是未定义的,而类类型对象将用默认构造函数进行初始化

string *ps=new string;//初始化为空string

int *pi=new int;//pi指向一个未初始化的int

传统的构造方式(圆括号):

int *pi=new int(1024);

我们传递给delete的指针必须指向动态分配的内存,或者是空指针,释放一块不是new分配的内存,或者将相同的指针释放多次,其行为是未定义的。

shared_ptr与new结合使用

我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式来初始化一个智能指针。

shared_ptr<int>p = new int(1024);//错误
shared_ptr<int>q(new int(1024));//正确

class shared                                    //一个拥有shared_ptr的类  
{
private:
    shared_ptr<int> p;                          //shared_ptr成员变量  
public:
    shared(shared_ptr<int> p_) :p(p_){}          //构造函数初始化shared_ptr      
    void print()                                //输出shared_ptr的引用计数和指向的值      
    {
        cout << "count:" << p.use_count()
            << "v =" << *p << endl;
    }
};
void print_func(shared_ptr<int> p)                //使用shared_ptr作为函数参数  
{
    //同样输出shared_ptr的引用计数和指向的值      
    cout << "count:" << p.use_count()
        << " v=" << *p << endl;
}
int main()
{
    shared_ptr<int> p(new int(100));
    shared s1(p), s2(p);                        //构造两个自定义类       
    s1.print();
    s2.print();
    *p = 20;                                    //修改shared_ptr所指的值      
    print_func(p);
    s1.print();
    system("pause");
}
/*输出为
count:3v =100
count:3v =100
count:4 v=20
count:3v =20
*/

在声明了shared_ptr和两个shared实例后,指针被它们所共享,因此引用计数为3.printf_func函数内部拷贝了一个shared_ptr对象,因此引用计数再增加1,但当退出函数时拷贝自动析构,引用计数又恢复3。

原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/3860456.html