【C++】const与shared_ptr使用中的一个细节

参考:记录以下boost::shared_ptr的一个使用细节

shared_ptr<T>::operator->返回的是T*类型指针,非const T*指针。因此通过const shared_ptr<T>&类型的ptr可以直接调用T各个原始的方法,不用担心const与非const问题
具体shared_ptr::operator->实现如下,摘自boost1.52.0版本boost\smart_ptr\shared_ptr.hpp

T * operator-> () const // never throws
{
      BOOST_ASSERT(px != 0);
      return px;
}

可以看出shared_ptr<T>operator->中的const修饰,是指shared_ptr<T>对象自身,而非shared_ptr所管理的对象

这个和普通原生指针还是有很大区别的,需要注意。

陈硕(@bnu_chenshuo)大牛对此有解释:const T*对应的是shared_ptr〈const T〉const shared_ptr〈T〉对应的是T* const。注意二者之间的差别

因此下面的代码是可以正确编译运行的:

#include <boost/shared_ptr.hpp>
#include <iostream>
 
using namespace std;
 
class Item
{
public:
    Item(){}
    ~Item(){}
     
    void set(int data) { data_ = data; }
     
    void print(void)
    {
        cout<<"Item::data_: "<<data_<<endl;
    }
     
private:
    int data_;
};
 
typedef boost::shared_ptr<Item> ItemPtr;
 
void foo(const ItemPtr& item)
{
    item->set(3); // 此处item对应于Item* const类型
}
 
int main ()
{
    ItemPtr item(new Item);  // 此处item对应于Item* 类型
    foo(item);
    item->print();
 
    return 0;
}```

### C++ 中 `std::shared_ptr` 的使用方法解析 #### 1. 定义基本功能 `std::shared_ptr` 是一种智能指针,属于 C++ 标准库 `<memory>` 头文件的一部分。它的主要作用是通过引用计数机制实现动态分配对象的自动管理[^2]。 - **所有权共享**:多个 `std::shared_ptr` 可以共同指向同一对象,每个实例都对该对象拥有一部分所有权。 - **控制块**:内部维护了一个控制块,记录当前对象的引用计数。当引用计数降为零时,对象会被自动释放并清理内存。 #### 2. 创建方式 以下是创建 `std::shared_ptr` 的常见方法: ```cpp #include <iostream> #include <memory> int main() { // 方法一:使用 make_shared 函数 (推荐) auto ptr1 = std::make_shared<int>(42); // 方法二:直接初始化 std::shared_ptr<int> ptr2(new int(10)); std::cout << *ptr1 << ", " << *ptr2 << std::endl; } ``` 上述代码展示了两种创建 `std::shared_ptr` 的方式。其中,`std::make_shared` 是更高效且安全的选择,因为它减少了两次内存分配操作[^1]。 --- #### 3. 拷贝赋值 `std::shared_ptr` 支持拷贝赋值操作,在这些过程中会更新引用计数。 ```cpp #include <iostream> #include <memory> int main() { std::shared_ptr<std::string> sptr1 = std::make_shared<std::string>("hello"); std::shared_ptr<std::string> sptr2; // 赋值操作 sptr2 = sptr1; std::cout << "sptr1 use count: " << sptr1.use_count() << "\n"; // 输出 2 std::cout << "sptr2 use count: " << sptr2.use_count() << "\n"; // 输出 2 return 0; } ``` 在此示例中,`use_count()` 方法返回当前对象的引用计数值。可以看到,经过赋值后,两个指针共享同一个对象的所有权。 --- #### 4. 自定义删除器 可以通过设置自定义删除器来改变默认的行为(即调用 `delete` 删除对象)。 ```cpp #include <iostream> #include <memory> void custom_deleter(int* p) { std::cout << "Custom deleter called\n"; delete p; } int main() { std::shared_ptr<int> sptr(new int(10), custom_deleter); // 当 sptr 超出范围时,custom_deleter 将被执行 } ``` 此代码片段演示了如何指定一个函数作为删除器,从而在对象销毁时执行特定逻辑。 --- #### 5. 应用场景分析 下面是一个基于 `std::shared_ptr` 构建 N 叉树节点的例子,类似于 Trie 结构的应用[^3]。 ```cpp #include <iostream> #include <vector> #include <memory> #include <unordered_map> using namespace std; // 定义 N 叉树节点 struct Node { char value; bool isEndOfWord; unordered_map<char, shared_ptr<Node>> children; Node(char c): value(c), isEndOfWord(false) {} }; class Trie { public: shared_ptr<Node> root; Trie(): root(make_shared<Node>(' ')) {} void insert(const string& word) { shared_ptr<Node> current = root; for (char c : word) { if (!current->children.count(c)) current->children[c] = make_shared<Node>(c); current = current->children[c]; } current->isEndOfWord = true; } bool search(const string& word) const { shared_ptr<Node> node = findNode(word); return node && node->isEndOfWord; } private: shared_ptr<Node> findNode(const string& prefix) const { shared_ptr<Node> current = root; for (char c : prefix) { if (!current->children.count(c)) return nullptr; current = current->children[c]; } return current; } }; ``` 在这个例子中,`std::shared_ptr` 确保了即使某些分支不再被访问,也不会发生内存泄漏。 --- #### 总结 `std::shared_ptr` 提供了一种方便的方式来进行动态内存管理,尤其适合多线程环境下的资源共享场景。然而需要注意的是,过度依赖可能会引发循环引用等问题,因此应谨慎设计数据结构。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值