[C++]智能指针


RAII:利用对象生命周期来控制程序资源,在构造时获取资源,析构的时释放资源。

auot_ptr

模拟实现:

template<class T>
class AutoPtr {
public:
    AutoPtr(T* ptr = nullptr)
        : _ptr(ptr) {}
 
    ~AutoPtr() {
        if (_ptr)
            delete _ptr;
    }
 
    AutoPtr(AutoPtr<T>& ap)
        : _ptr(ap._ptr) {
        // 转移资源管理权
        ap._ptr = NULL;
    }
 
    AutoPtr<T>& operator=(AutoPtr<T>& ap) {
        if (this != &ap) {
            if (_ptr)
                delete _ptr;
            // 转移资源管理权
            _ptr = ap._ptr;
            ap._ptr = NULL;
        }
        return *this;
    }
 
    // 像指针一样的操作
    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
private:
    T* _ptr;
};

Bug:

AutoPtr<T> ap(new T);
AutoPtr<T> copy(ap);// 拷贝后把ap对象的指针赋空了,通过ap对象访问资源时就会出bug(除非每次判断ap._ptr是否不为空)

所以auto_ptr根本用不了。

C++11: unique_ptr

也叫scoped_ptr(boost库)

template<class T>
class UniquePtr {
public:
    UniquePtr(T* ptr = nullptr)
        : _ptr(ptr) {}

    ~UniquePtr() {
        if (_ptr)
            delete _ptr;
    }

	// unique_ptr并没有去实现类似scoped_array的unique_array,因为标准库中有vector
	// T& operator[](size_t index) {
    //     return _ptr[index];
    // } 
    // const T& operator[](size_t index)const {
    //     return _ptr[index];
    // }

    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
private:
    // C++11
    UniquePtr(UniquePtr<T> const &) = delete;
    UniquePtr & operator=(UniquePtr<T> const &) = delete;
private:
    T * _ptr;
}

相比auto_ptr,简单粗暴的防拷贝,勉强可以使用,但没有从根本解决问题。

C++11: shared_ptr

template <class T>
class SharedPtr {
public:
    SharedPtr(T* ptr = nullptr)
        : _ptr(ptr)
        , _pRefCount(new int(1))
        , _pMutex(new mutex) {}

    ~SharedPtr() { Release(); }

    SharedPtr(const SharedPtr<T>& sp)
        : _ptr(sp._ptr)
        , _pRefCount(sp._pRefCount)
        , _pMutex(sp._pMutex) {
        AddRefCount();
    }

    SharedPtr<T>& operator=(const SharedPtr<T>& sp) {
        if (_ptr != sp._ptr) {
            Release();
            // 共享管理新对象的资源,并增加引用计数
            _ptr = sp._ptr;
            _pRefCount = sp._pRefCount;
            _pMutex = sp._pMutex;
            AddRefCount();
        }
        return *this;
    }

    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
    int UseCount() { return *_pRefCount; }
    T* Get() { return _ptr; }
private:
    void AddRefCount() {
        // 加锁或者使用加1的原子操作
        _pMutex->lock();
        ++(*_pRefCount);
        _pMutex->unlock();
    }

    void Release() {
        bool deleteflag = false;
        // 引用计数减1,如果减到0,则释放资源
        _pMutex.lock();
        if (--(*_pRefCount) == 0) {
            delete _ptr;
            delete _pRefCount;
            deleteflag = true;
        }
        _pMutex.unlock();

        if (deleteflag == true)
            delete _pMutex;
    }

    int* _pRefCount; // 引用计数
    T* _ptr; // 指向管理资源的指针
    mutex* _pMutex; // 互斥锁
};
仿函数删除器

上面代码析构函数是用delete来释放资源的,但是我们可能用以下几种方式申请资源:
SharedPtr<int> p(new int);
SharedPtr<FILE> fp(fopen("./test","r"));
SharedPtr<int> mp = ((int*)malloc(sizeof(int)));
这时候使用delete来释放,可能会出错,这时候就需要自定义删除方式,我们只需对上面代码稍加修改即可:

// 定义我们自己的删除方式
template<class T>
class Delete {
public:
    void operator()(T*& p) {
        if (p != nullptr) {
            delete p;
            p = nullptr;
        }
    }
};

template<class T>
class Free {
public:
    void operator()(T*& p) {
        if (p != nullptr) {
            free(p);
            p == nullptr;
        }
    }
};

class Close {
public:
    void operator()(FILE*& p) {
        if (p != nullptr) {
            fclose(p);
            p = nullptr;
        }
    }
};

template <class T, class D = Delete<T>>
class SharedPtr {
public:
	// 其他都不变,修改析构函数即可
	void Release() {
        bool deleteflag = false;
        // 引用计数减1,如果减到0,则释放资源
        _pMutex.lock();
        if (--(*_pRefCount) == 0) {
            D()(_ptr); // 创建匿名对象,并调()重载
            delete _pRefCount;
            deleteflag = true;
        }
        _pMutex.unlock();

        if (deleteflag == true)
            delete _pMutex;
    }
}

使用方式:
SharedPtr<int> np(new int);
SharedPtr<FILE, Close<FILE>> fp(fopen("./test","r"));
SharedPtr<int, Free<int>> mp((int*)malloc(sizeof(int)));

shared_ptr的循环引用

shared_ptr并非完美,也有小缺陷

比如:

struct ListNode {
    int _data;
    shared_ptr<ListNode> _prev;
    shared_ptr<ListNode> _next;
    ~ListNode() { cout << "~ListNode()" << endl; }
};
void test() {
    shared_ptr<ListNode> node1(new ListNode);
    shared_ptr<ListNode> node2(new ListNode);
    node1->_next = node2;
    node2->_prev = node1;
} // 这里会导致内存泄漏

在这里插入图片描述
出作用域后
node1和node2对象被释放
在这里插入图片描述
但是引用计数不为0,_date不会被释放,造成内存泄漏。

当然,C++11库中也给出了响应的解决方法,就是weak_ptr

weak_ptr

weak_ptr要和shared_ptr搭配使用,在进行如上的赋值时,并不进行引用计数的加加操作,这也保证了在释放的时候不会因为引用计数不为0而没有正确释放,造成内存泄漏。

struct ListNode {
    int _data;
    weak_ptr<ListNode> _prev;
	weak_ptr<ListNode> _next;
    ~ListNode() { cout << "~ListNode()" << endl; }
};

C++11 守卫锁

lock_guard(#include <mutex>)利用RAII思想,通过对象的生命周期控制锁的生命周期构造加锁,析构解锁,防止死锁。

template<class Mutex>
class LockGuard {
public:
    LockGuard(Mutex& mtx)
        :_mutex(mtx) {
        _mutex.lock();
    }
    ~LockGuard() {
        _mutex.unlock();
    }
    LockGuard(const LockGuard<Mutex>&) = delete;
private:
    // 必须使用引用,保证同一个互斥量对象
    Mutex& _mutex;
};

void Fuc() {
    mutex mtx;
    // 进入作用域构造lg对象,加锁
    {
        LockGuard<mutex> lg(mtx);
        // ...code
        // ...code
        // ...code
    }
    // 出了作用域析构lg对象,解锁
}
智能网联汽车的安全员高级考试涉及多个方面的专业知识,包括但不限于自动驾驶技术原理、车辆传感器融合、网络安全防护以及法律法规等内容。以下是针对该主题的一些核心知识点解析: ### 关于智能网联车安全员高级考试的核心内容 #### 1. 自动驾驶分级标准 国际自动机工程师学会(SAE International)定义了六个级别的自动驾驶等级,从L0到L5[^1]。其中,L3及以上级别需要安全员具备更高的应急处理能力。 #### 2. 车辆感知系统的组成与功能 智能网联车通常配备多种传感器,如激光雷达、毫米波雷达、摄像头超声波传感器等。这些设备协同工作以实现环境感知、障碍物检测等功能[^2]。 #### 3. 数据通信与网络安全 智能网联车依赖V2X(Vehicle-to-Everything)技术进行数据交换,在此过程中需防范潜在的网络攻击风险,例如中间人攻击或恶意软件入侵[^3]。 #### 4. 法律法规要求 不同国家地区对于无人驾驶测试及运营有着严格的规定,考生应熟悉当地交通法典中有关自动化驾驶部分的具体条款[^4]。 ```python # 示例代码:模拟简单决策逻辑 def decide_action(sensor_data): if sensor_data['obstacle'] and not sensor_data['emergency']: return 'slow_down' elif sensor_data['pedestrian_crossing']: return 'stop_and_yield' else: return 'continue_driving' example_input = {'obstacle': True, 'emergency': False, 'pedestrian_crossing': False} action = decide_action(example_input) print(f"Action to take: {action}") ``` 需要注意的是,“橙点同学”作为特定平台上的学习资源名称,并不提供官方认证的标准答案集;建议通过正规渠道获取教材并参加培训课程来准备此类资格认证考试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值