面试之快速学习C++11-完美转发,nullptr, shared_ptr,unique_ptr,weak_ptr,shared_from_this

这篇具有很好参考价值的文章主要介绍了面试之快速学习C++11-完美转发,nullptr, shared_ptr,unique_ptr,weak_ptr,shared_from_this。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

完美转发及其实现

  1. 函数模版可以将自己的参数完美地转发给内部调用的其他函数。所谓完美,即不仅能准确地转发参数的值,还能保证被转发参数的左右值属性不变
  2. 引用折叠:如果任一引用为左值引用,则结果为左值引用,否则为右值引用。
& && -> &
&& & -> &
& & -> &
&& && -> &&
void actualRun(int a) {
    
}
template <typename T>
void testPerfectForward(T &&param) {
    actualRun(param);
}

void testPerfectForwardMain() {
    int a = 0;
    testPerfectForward(a);
}

上述 T 为int &。 那么整个为 int & &&-> int &

回到完美转发,假设现在我需要转发a,那么注意一下实现完美转发需要这样写


template <typename T>
void testPerfectForward1(T &&param) {
    actualRun(std::forward(param));
}

forward大致实现原理
static_cast + &&

template <typename T>
T&& forwad(T &param) {
    return static_cast<T&&>(param);
}

注意其实std::move底层实现也是 static_cast

C++11 nullptr:初始化空指针

  1. #define NULL 0
#include <iostream>
using namespace std;

void isnull(void *c){
    cout << "void*c" << endl;
}
void isnull(int n){
    cout << "int n" << endl;
}
void testNull1() {
    isnull(0);
    //isnull(NULL);//Call to 'isnull' is ambiguous
    isnull((void*)NULL);
    /*
     int n
     void*c
     */
}

1 . nullptr 是 nullptr_t 类型的右值常量,专用于初始化空类型指针。nullptr_t 是 C++11 新增加的数据类型,可称为“指针空值类型”。也就是说,nullpter 仅是该类型的一个实例对象(已经定义好,可以直接使用),如果需要我们完全定义出多个同 nullptr 完全一样的实例对象。

  1. nullptr 可以被隐式转换成任意的指针类型。故如下:

void testNull2() {
    isnull(0);
    //isnull(NULL);//Call to 'isnull' is ambiguous
    isnull((void*)NULL);
    isnull(nullptr);
    
    /*
     int n
     void*c
     void*c
     */
    
}
  1. 借助执行结果不难看出,由于 nullptr 无法隐式转换为整形,而可以隐式匹配指针类型,因此执行结果和我们的预期相符
void testNullMain() {
//    int *p = 0;
//    int *q = NULL;
//    testNull1(0);
//    testNull1(NULL);
}

.C++11 shared_ptr智能指针

void deleteInt(int *p) {
    delete []p;
}
void testSharedPtr () {
    std::cout << "testSharePtr: " << endl;
    //初始化空的shareptr,引用计数为0不是1
    std::shared_ptr<int> p1;
    std::shared_ptr<int> p2(nullptr);
    
    std::shared_ptr<int> p3(new int(10));
    std::shared_ptr<int> p4 = std::make_shared<int>(10);
    
    //调用拷贝构造函数
    std::shared_ptr<int> p5(p4);  //或者 p4  = p3;
    //调用移动构造函数
    std::shared_ptr<int> p6(std::move(p4)); //或者p6 = std::move(p4)
    
    //智能指针可以拷贝,给多个智能指针用,引用计数+1,但是普通指针,只能拷贝给一个智能指针
    int *p = new int(1);
    std::shared_ptr<int> pp1(p);
//    std::shared_ptr<int> pp2(p); //错误!!!!
    
    // 在初始化 shared_ptr 智能指针时,还可以自定义所指堆内存的释放规则,这样当堆内存的引用计数为 0 时,会优先调用我们自定义的释放规则。在某些场景中,自定义释放规则是很有必要的,比如,对于申请的动态数组来说,share—_ptr指针默认的释放规则是不支持释放数组的,值呢个自定义对于的释放规则,如下:
    //释放规则可以使用 C++11 标准中提供的 default_delete<T> 模板类,我们也可以自定义释放规则:
    std::shared_ptr<int> p10(new int[10], std::default_delete<int[]>());
    std::shared_ptr<int> p11(new int[10], deleteInt);
    std::shared_ptr<int> p12(new int[10], [](int *p){delete []p;});
    
    std::shared_ptr<int> ppp1 = std::make_shared<int>(10);
    std::shared_ptr<int> ppp2(ppp1);
    
    std::cout << *ppp2 << endl;
    cout<< ppp2.use_count()<<endl;
    ppp1.reset();
    if (p1) {
        std::cout << "ppp1 is not null !"<< endl;
    } else {
        std::cout << "ppp1 is null !"<< endl;
    }
    std::cout << *ppp2 << endl;
    cout<< ppp2.use_count()<<endl;
}

1 shared_ptr<T>模板类常用成员方法
 成员方法名    功 能
 operator=()    重载赋值号,使得同一类型的 shared_ptr 智能指针可以相互赋值。
 operator*()    重载 * 号,获取当前 shared_ptr 智能指针对象指向的数据。
 operator->()    重载 -> 号,当智能指针指向的数据类型为自定义的结构体时,通过 -> 运算符可以获取其内部的指定成员。
 swap()    交换 2 个相同类型 shared_ptr 智能指针的内容。
 reset()    当函数没有实参时,该函数会使当前 shared_ptr 所指堆内存的引用计数减 1,同时将当前对象重置为一个空指针;当为函数传递一个新申请的堆内存时,则调用该函数的 shared_ptr 对象会获得该存储空间的所有权,并且引用计数的初始值为 1get()    获得 shared_ptr 对象内部包含的普通指针。
 use_count()    返回同当前 shared_ptr 对象(包括它)指向相同的所有 shared_ptr 对象的数量。
 unique()    判断当前 shared_ptr 对象指向的堆内存,是否不再有其它 shared_ptr 对象再指向它。
 operator bool()    判断当前 shared_ptr 对象是否为空智能指针,如果是空指针,返回 false;反之,返回 true。
 */

C++11 unique_ptr智能指针

unique_ptr 指针指向的堆内存无法同其它 unique_ptr 共享,也就是说,每个 unique_ptr 指针都独自拥有对其所指堆内存空间的所有权

void testUniqueptr() {
    std::unique_ptr<int> p1(new int(3));
//    std::unique_ptr<int> p1(p2);
    std::unique_ptr<int> p2(std::move(p1));
    // 默认情况下,unique_ptr 指针采用 std::default_delete<T> 方法释放堆内存。当然,我们也可以自定义符合实际场景的释放规则。值得一提的是,和 shared_ptr 指针不同,为 unique_ptr 自定义释放规则,只能采用函数对象的方式。例如:
    struct myDel {
        void operator()(int *p) {
            delete p;
        }
    };
    std::unique_ptr<int, myDel> p7(new int);
//    std::unique_ptr<int, myDel> p6(new int);
    
    std::unique_ptr<int> p10(new int);
    *p10 = 10;
    //p10释放当前所指堆的所有权, 但该存储空间不会被销毁,转移给了p
    int *p = p10.release();
    
    std::unique_ptr<int> p11;
    //中 p 表示一个普通指针,如果 p 为 nullptr,则当前 unique_ptr 也变成空指针;反之,则该函数会释放当前 unique_ptr 指针指向的堆内存(如果有),然后获取 p 所指堆内存的所有权(p 为 nullptr)。
    p11.reset(p);
    
//    int *p2 = p;
}

C++11 weak_ptr智能指针

weak_ptr是为了配合shared_ptr而引入的一种智能指针,它不具有普通指针的行为,没有重载*和->两个操作符,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。
weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。
使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count()==0,但更快,表示被观测的资源 (也就是shared_ptr的管理的资源)已经不复存在。
weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr 获得一个可用的shared_ptr对象,从而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr。

shared_from_this

#include<memory>

class Test: public std::enable_shared_from_this<Test>
{
 public:  
  Test();
  ~Test();
  std::shared_ptr<Test> getSharedFromThis(){return shared_from_this();}
}

在什么情况下要使类A继承enable_share_from_this?

使用场合:当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。

我们就使类A继承enable_share_from_this,然后通过其成员函数share_from_this()返回当指向自身的share_ptr。

以上有2个疑惑:

1.把当前类对象作为参数传给其他函数时,为什么要传递share_ptr呢?直接传递this指针不可以吗?

一个裸指针传递给调用者,谁也不知道调用者会干什么?假如调用者delete了该对象,而share_tr此时还指向该对象。

2.这样传递share_ptr可以吗?share_ptr

这样会造成2个非共享的share_ptr指向一个对象,最后造成2次析构该对象。
————————————————
引用链接:https://blog.csdn.net/zk3326312/article/details/79108690
http://c.biancheng.net/view/3730.html文章来源地址https://www.toymoban.com/news/detail-658194.html

到了这里,关于面试之快速学习C++11-完美转发,nullptr, shared_ptr,unique_ptr,weak_ptr,shared_from_this的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++11『右值引用 ‖ 完美转发 ‖ 新增类功能 ‖ 可变参数模板』

    ✨个人主页: 北 海 🎉所属专栏: C++修行之路 🎃操作环境: Visual Studio 2022 版本 17.6.5 自从C++98以来,C++11无疑是一个相当成功的版本更新。它引入了许多重要的语言特性和标准库增强,为C++编程带来了重大的改进和便利。C++11的发布标志着C++语言的现代化和进步,为程序员

    2024年02月05日
    浏览(50)
  • 论 shared_ptr的线程安全

    今天有同事问我shared_ptr是线程更安全的吗?我当时脑子一懵,有点不确定。 但回过神来仔细一想这什么鸟问题,c++ stl里有线程安全的吗,shared_ptr 也不是针对线程安全而设计出来的呀,八竿子打不着的东西为什么会凑在一起问。 好像也就一个atmoic引用计数可以沾上边。 首先

    2024年02月08日
    浏览(38)
  • C++智能指针shared_ptr详解

    C++智能指针shared_ptr是一种可以自动管理内存的智能指针,它是C++11新增的特性之一。与传统指针不同,shared_ptr可以自动释放所管理的动态分配对象的内存,并避免了手动释放内存的繁琐操作,从而减少了内存泄漏和野指针的出现。 shared_ptr是一个模板类,通过引用计数器实现

    2023年04月22日
    浏览(41)
  • C++智能指针shared_ptr用法

    写在前面的总结: 一个shared_ptr对象管理一个指针(new T,在堆空间),多个shared_ptr对象可以管理同一个指针,只有某个shared_ptr对象第一次初始化指针时才执行指针的构造函数,管理同一个指针的shared_ptr对象个数称为引用计数,这个引用计数保存在每个管理该指针的shared_p

    2024年02月03日
    浏览(56)
  • 【C++11】 initializer_list | 右值引用 | 移动构造 | 完美转发

    { } 初始化 C++11 扩大了括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义类型, 使用初始化列表,可添加等号(=),也可不添加 将1赋值给x1,x2处省略了赋值符号,将5赋值给x2 同样也可以将new开辟4个int的空间初始化为0 创建对象时,可以使用列

    2024年02月08日
    浏览(71)
  • 【C++干货铺】C++11新特性——右值引用、移动构造、完美转发

    ========================================================================= 个人主页点击直达:小白不是程序媛 C++系列专栏:C++干货铺 代码仓库:Gitee ========================================================================= 目录 左值与左值引用 右值与右值引用 左值引用和右值引用的比较  左值引用总结:

    2024年01月25日
    浏览(39)
  • C++智能指针shared_ptr使用详解

    shared_ptr 是一个共享所有权的智能指针,允许多个指针指向同一个对象。 ​ shared_ptr 使用 引用计数 ,每一个shared_ptr的拷贝都指向相同的内存。每使用它一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,释放所指向的堆内存。shared_ptr内部的引用计数是安

    2024年02月07日
    浏览(41)
  • shared_ptr和unique_ptr主动释放

    shared_ptr和unique_ptr均可以采用reset()来进行释放,unique_ptr调用了reset之后就会直接释放掉,shared_ptr则会在所有引用计数变为0的时候才会释放申请的内存。 注意unique_ptr的release()方法,并不会释放资源,只会把unique_ptr置为空指针,原来那个资源可以继续调用 reset 结果: 在reset之

    2024年02月14日
    浏览(39)
  • 深入理解和应用C++ std::shared_ptr别名构造函数

    在现代C++中,智能指针是一个极为重要的工具,尤其std::shared_ptr以其自动内存管理、引用计数和多线程安全性等特性深受开发者喜爱。其中一个不太常用但功能强大的构造方式是 别名构造函数 ,它允许我们创建一个共享相同底层对象但是指向其内部不同数据成员或子对象的

    2024年01月16日
    浏览(46)
  • 【C++入门到精通】智能指针 shared_ptr 简介及C++模拟实现 [ C++入门 ]

    在 C++ 动态内存管理中,除了 auto_ptr 和 unique_ptr 之外,还有一种 智能指针 shared_ptr ,它可以让多个指针共享同一个动态资源,并且能够自动释放资源。 shared_ptr 通过引用计数的方式来管理内存,能够避免程序中出现悬空指针和内存泄漏等问题 。本文将介绍 shared_ptr 的简介和

    2024年01月22日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包