• auto_ptr为什么不能做为vector的元素


      昨天看effectve c++的时候,发现了auto_ptr这个东西。由于我待过的公司都是用的老版c++,代码里智能指针什么的完全没有出现过,都是直接操作的原始指针。虽说我很少出错,但是总归还是不太安全。言归正传,说回auto_ptr,这个东西一开始我也见过,但是当时在赶项目也就没有怎么上心,这回正好看到了,就详细了解下。

      在effiectev c++中我了解到,这是老版c++里的智能指针(之前我只知道c++11里的share_ptr和unique_ptr),同一个对象从始至终只会有一个auto_ptr指向它,也就是说当指向某个对象的auto_ptr被拷贝时(拷贝构造或者是赋值),原auto_ptr会被置为NULL。当指向对象的auto_ptr离开作用域后,会自动调用析构函数,从而达到防止资源泄露的目的。

      很自然的,我想将我最近的新项目由操作裸指针改为智能指针,因为在项目中用到了STL标准容器,所以打算先用vector测试下auto_ptr。测试代码如下:

    #include<iostream>
    #include<vector>
    #include<memory>
    
    class Test{
    public:
        Test() {
            std::cout << "init" << std::endl;
        }
        
        ~Test() {
            std::cout << "del" << std::endl;
        }
    };
    
    int main()
    {
        std::auto_ptr<Test> ap(new Test());
        
        std::vector<std::auto_ptr<Test> > vec;
        vec.push_back(ap);
        
        std::cout << ap.get() << std::endl;
        return 0;
    }

      编译时,提示auto_ptr过时的警告就不提了,报错如下:

    /usr/include/c++/7/ext/new_allocator.h:136:4: error: no matching function for call to ‘std::auto_ptr<Test>::auto_ptr(const std::auto_ptr<Test>&)’ 
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

      当时可能警告加报错信息太长,我没有看到这个const。。。然后想了很久想不通为什么不行,我当时的理解是vector将auto_ptr拷贝进去,原auto_ptr将变为0。然后怀疑自己将vector的push_back操作记错了,打开stl源码解析,找到vector加入元素时构造的函数:

    template <class T1, class T2>
    inline void construct(T1* p, const T2& value) 
    {
        new (p) T1(value);       
    }

      嗯?我没记错啊,为什么不能呢?然后我去网上搜了下,知道真相的我眼泪掉了下来。很简单:

    因为将auto_ptr拷贝时需要对原auto_ptr进行修改,也就是将原auto_ptr置为NULL,所以不能支持以const的方式进行拷贝构造!

      也就是说,auto_ptr是不能做为STL标准容器的元素的。

      对于这个疑问的出现,我想一方面是自己不够细心,没有仔细看报错的含义;另一方面是自己的思维还有点欠缺,明明知识点都知道,但是没联想到。

  • 相关阅读:
    /、./和../的区别
    【Java基础】-- FileUtils工具类常用方法
    【数据库】-- MySQL中比like更高效的三个写法
    【Java框架】-- SpringBoot大文件RestTemplate下载解决方案
    记一次gitlab代码仓清空还原复盘
    聊聊如何实现一个带有拦截器功能的SPI
    聊聊如何实现一个支持键值对的SPI
    类实例对象的class类型却不属于该类,何解?
    exe打包成安装文件(界面美观)
    linux系统软件启动sh脚本
  • 原文地址:https://www.cnblogs.com/RookieSuperman/p/11257446.html
Copyright © 2020-2023  润新知