文档章节

C++11 智能指针

y
 yepanl
发布于 09/24 21:35
字数 868
阅读 23
收藏 0

    C++11提供了三个智能指针,std::shared_ptr,std::unique_ptr,std::weak_ptr。最常用的是shared_ptr和unique_ptr。

    (1)std::shared_ptr

            shared_ptr是共享指针,通过在控制块中增加引用计数的方式实现多个指针指向同一个对象。每当拷贝构造或者拷贝赋值时,对象的引用计数都会+1,每当指针对象析构时,引用计数-1,直到引用计数为0,释放实际指针对象。

            std::shared_ptr<T> sp(new T()) 形式声明效率上没有 std::shared_ptr<T> sp = std::make_shared<T>()高,因为前一种声明方式在实现上需要new两次(一次是new T, 一次是 new 控制结构),而后者在实现上一般都是一次。

示例如下:

#include <iostream>
#include <memory>

int main() {
    {
        std::shared_ptr<int> sp1;

        {
            std::shared_ptr<int> sp2(new int(10));
            sp1 = sp2;
            std::cout << "sp1.count=" << sp1.use_count() << std::endl;    // use_count为2
        }
        std::cout << "sp1.count=" << sp1.use_count() << std::endl;        // use_count为1
    }

    return 0;
}

 

    2,std::unique_ptr

        unique_ptr顾名思义,只允许一个指针指向同一个对象。unique_ptr通过禁止拷贝构造函数和拷贝赋值运算符到达无法让多个指针指向同一个对象的目的。unique_ptr通过移动构造函数和移动赋值运算符达到指针对象资源转移的目的(保证某一时刻只有一个指针指向该对象)。

        同样,std::unique_ptr<T> sp(new T()) 形式声明效率上没有 std::unique_ptr<T> sp = std::make_unique<T>()高,因为前一种声明方式在实现上需要new两次(一次是new T, 一次是 new 控制结构),而后者在实现上一般都是一次。

示例如下:

#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int> sp1(new int(10));
//    std::unique_ptr<int> sp2 = sp1;                    // 编译错误,拷贝构造函数 deleted
    std::unique_ptr<int> sp2 = std::move(sp1);    // ok,使用移动构造函数,实现资源转移

    return 0;
}
 

    3,std::weak_ptr

        std::shared_ptr在循环引用的情况下会有内存泄漏的问题,示例如下:

#include <iostream>
#include <memory>

class Child;
class Parent;

class Parent {
private:
    std::shared_ptr<Child> ChildPtr;

public:
    void setChild(std::shared_ptr<Child> child) {
        this->ChildPtr = child;
    }

    ~Parent() {}
};

class Child {
private:
    std::shared_ptr<Parent> ParentPtr;

public:
    void setPartent(std::shared_ptr<Parent> parent) {
        this->ParentPtr = parent;
    }

    ~Child() {}
};

int main() {
    std::weak_ptr<Parent> wpp;
    std::weak_ptr<Child> wpc;
    {
        std::shared_ptr<Parent> p(new Parent);
        std::shared_ptr<Child> c(new Child);
        p->setChild(c);
        c->setPartent(p);
        wpp = p;
        wpc = c;
        std::cout << p.use_count() << std::endl; // 2
        std::cout << c.use_count() << std::endl; // 2
    }
    std::cout << wpp.use_count() << std::endl;  // 1
    std::cout << wpc.use_count() << std::endl;  // 1
    return 0;
}
    说明:本质上来说,由于循环相互引用,导致双方都没有减少对方的引用计数,导致双方资源都没有释放掉。

    std::weak_ptr提供了一种资源监视的方法:使用weak_ptr指向一个shared_ptr,并不会增加对象的引用计数,但是可以访问shared_ptr的控制块结构。解决上述循环引用问题的示例代码如下:

    

#include <iostream>
#include <memory>

class Child;
class Parent;

class Parent {
private:
    std::shared_ptr<Child> ChildPtr;

public:
    void setChild(std::shared_ptr<Child> child) {
        this->ChildPtr = child;
    }

    ~Parent() {}
};

class Child {
private:
//    std::shared_ptr<Parent> ParentPtr;
    std::weak_ptr<Parent> ParentPtr;

public:
    void setPartent(std::shared_ptr<Parent> parent) {
        this->ParentPtr = parent;
    }

    ~Child() {}
};

int main() {
    std::weak_ptr<Parent> wpp;
    std::weak_ptr<Child> wpc;
    {
        std::shared_ptr<Parent> p(new Parent);
        std::shared_ptr<Child> c(new Child);
        p->setChild(c);
        c->setPartent(p);
        wpp = p;
        wpc = c;
        std::cout << p.use_count() << std::endl;   // 1
        std::cout << c.use_count() << std::endl;   // 2
    }
    std::cout << wpp.use_count() << std::endl;  // 0
    std::cout << wpc.use_count() << std::endl;  // 0
    return 0;
}
 

© 著作权归作者所有

共有 人打赏支持
y
粉丝 0
博文 52
码字总数 38753
作品 0
南京
程序员
C++11 智能指针

原作者:BabuAbdulsalam 本文翻译自CodeProject,转载请注明出处。 引入 尽管有另外一篇文章说里的智能指针了。近来,我听到许多人谈论新标准,就是所谓的。 我研究了一下的一些语言特性,发...

2017/12/28
0
0
C++ 11和C++98相比有哪些新特性

此文是如下博文的翻译: https://herbsutter.com/elements-of-modern-c-style/ C++11标准提供了许多有用的新特性。这篇文章特别针对使C++11和C++98相比看上去像一门新语言的特性,因为: C+...

harlanc
2017/03/05
0
0
消灭“脑细胞杀手”,阿里专家带你深入C++对象的生命周期管理

摘要:C/C++的指针一直是令人又爱又恨的特性。围绕指针产生了许许多多优雅的数据结构和系统实现,但又滋生了不少“脑细胞杀手”——内存Bug。C/C++指针问题(空指针、野指针、垂悬指针)的根...

萌萌怪兽
04/18
0
0
一个函数指针模板,向std::function致敬

两年前写这个是因为学C++11练手。而且也因为sizeof(std::function<void()>)的大小有点大,不是指针大小。所以自己写个只有指针大小的版本,不过功能就少很多。 这样就可以这么用: 基本的思路...

大止刀口
2016/05/02
255
0
c++ primer 第五版学习笔记

第二章 函数体外定义的内置类型变量会初始化为0,函数体外的是未初始化的 用constexpr声明变量表示它是一个常量表达式(编译器可以确定的值),且只能应用于字面值 c++11中可以用 来定义一个...

David栗子
2017/12/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

线性一致性和 Raft

作者:沈泰宁 在讨论分布式系统时,共识算法(Consensus algorithm)和一致性(Consistency)通常是讨论热点,两者的联系很微妙,很容易搞混。一些常见的误解:使用了 Raft [0] 或者 paxos ...

TiDB
21分钟前
0
0
兄弟连区块链教程以太坊源码分析core-state-process源码分析

## StateTransition状态转换模型 /* The State Transitioning Model 状态转换模型 A state transition is a change made when a transaction is applied to the cu......

兄弟连区块链入门教程
23分钟前
0
0
linear-gradient渐变中的参数

在看张鑫旭的博客 遇到渐变数值后面带参数不太理解 @supports (-webkit-mask: none) or (mask: none) { .box { border: none; background: linear-gradient(to bottom, #34538...

红羊在厦门
24分钟前
0
0
Python yagmail模块自动发邮件

Python发邮件yagmail模块 import yagmail#连接服务器yag=yagmail.SMTP('xx@163.com','yy','smtp.163.com')#邮箱正文contents=["test","email send"]#发送邮件#yag.send('...

小白兔_球球
25分钟前
1
0
pada mysql

CREATE SCHEMA `exchange` DEFAULT CHARACTER SET utf8mb4 ;

qwfys
34分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部