29_this指针的使用

1、当形参和成员变量同名时,可用this指针来区分

class Data
{
public:
    int num;

    //形参 和成员名相同
    void setNum(int num)
    {
        //形参num
        //成员num  this->num
        //num= num;//就近原则 形参num 赋值给 形参num
        this->num = num;
        //将形参num 赋值给 对象中成员num
    }
};

2、在类的普通成员函数中返回对象本身(*this)(重要)

class MyCout
{
public:
    MyCout& myCout(char *str)
    {
        cout<<str;
        return *this;//*this 代表就是 当前调用该函数的对象
    }
};
int main(int argc, char *argv[])
{
    MyCout ob;
    /*
    ob.myCout("hehe");
    ob.myCout("haha");
    ob.myCout("xixi");*/
    
    ob.myCout("hehe").myCout("haha").myCout("xixi");//ob.myCout("hehe") == ob

    return 0;
}

运行结果:

 

<think> 我们正在讨论C++中的`shared_from_this`,它是通过继承`std::enable_shared_from_this`来获得的一个成员函数,用于在对象内部安全地获取一个指向当前对象的`std::shared_ptr`。 根据引用内容,我们需要注意以下几点: 1. 只能在已经被`std::shared_ptr`管理的对象上调用`shared_from_this`。 2. 不能在构造函数中调用`shared_from_this`,因为此时对象还未被`shared_ptr`管理(即引用计数机制还未建立)。 3. 使用`shared_from_this`可以避免创建多个独立的`shared_ptr`指向同一个对象(否则会导致多次释放)。 下面我将详细介绍`shared_from_this`的使用方法、原理以及注意事项。 ## 1. 为什么需要`shared_from_this`? 考虑以下场景:一个对象需要传递自身的智能指针给其他函数(比如异步操作、回调函数等),以保证在操作过程中对象不会被意外销毁。如果我们直接使用`this`指针来创建新的`shared_ptr`,那么就会存在多个独立的`shared_ptr`控制块,导致同一个内存被多次释放。 例如(引用[4]中的错误示例): ```cpp #include <iostream> #include <memory> struct Node { ~Node() { std::printf("[%p] %s\n", this, __func__); } std::shared_ptr<Node> make_this_share_ptr() { return std::shared_ptr<Node>(this); // 错误:会导致多个独立的shared_ptr } }; void test(Node* p) { std::shared_ptr<Node> sp1 = p->make_this_share_ptr(); std::shared_ptr<Node> sp2 = p->make_this_share_ptr(); // 两个独立的shared_ptr,会导致两次释放 } int main() { Node* p = new Node{}; test(p); // 忘记delete p,但实际上在test函数中已经释放了两次,程序崩溃 } ``` 为了解决这个问题,C++11引入了`std::enable_shared_from_this`模板类。 ## 2. 如何使用`shared_from_this`? 正确的方法是让类`T`继承自`std::enable_shared_from_this<T>`,然后通过成员函数`shared_from_this`来获取共享指针。 示例: ```cpp #include <memory> #include <iostream> class MyClass : public std::enable_shared_from_this<MyClass> { public: std::shared_ptr<MyClass> getShared() { return shared_from_this(); // 安全地返回一个共享指针 } }; int main() { std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>(); std::shared_ptr<MyClass> ptr2 = ptr1->getShared(); // 正确,两个shared_ptr共享同一个控制块 std::cout << ptr1.use_count() << std::endl; // 输出2 } ``` 注意:对象必须已经被`shared_ptr`管理,否则调用`shared_from_this`会抛出`std::bad_weak_ptr`异常。 ## 3. 注意事项 - **不能在构造函数中调用**:因为此时对象还没有被交给`shared_ptr`管理,也就是内部的`weak_this_`成员还没有被初始化(引用[1]和[2])。 - **对象必须由`shared_ptr`管理**:如果对象是在栈上创建的(局部变量),则不能使用`shared_from_this`(引用[5])。 - **整个程序应统一使用智能指针**:避免混合使用原始指针和智能指针(引用[1])。 ## 4. 原理 `std::enable_shared_from_this`内部有一个`weak_ptr`成员(通常命名为`weak_this_`),它不会增加引用计数,但可以用于获取`shared_ptr`。当使用`shared_ptr`构造一个对象时(比如通过`std::make_shared`或`std::shared_ptr`的构造函数),如果该对象继承自`enable_shared_from_this`,则`shared_ptr`的构造函数会初始化这个`weak_this_`成员,使其指向当前`shared_ptr`的控制块。 当调用`shared_from_this()`时,它内部实际上是调用`weak_this_.lock()`来获取一个`shared_ptr`。如果`weak_this_`还未初始化(即没有被`shared_ptr`管理过),则`lock()`会返回一个空的`shared_ptr`,但标准要求此时抛出`std::bad_weak_ptr`异常。 ## 5. 应用场景 引用[5]中提到: - 异步编程:在异步操作中,需要确保回调函数执行时对象仍然存在。 - 观察者模式:被观察者持有观察者的弱引用,观察者可能需要传递自身的共享指针给被观察者。 - 链式调用:返回自身的共享指针以支持链式调用。 - 回调函数:在回调中保持对象生命周期。 ## 总结 `shared_from_this`是一个强大的工具,用于在对象内部获取自身的安全共享指针使用时必须确保对象已被`shared_ptr`管理,且不能在构造函数中使用。 下面生成几个相关问题: §§相关问题§§ 1. 为什么不能在构造函数中调用`shared_from_this`? 2. 如何安全地构造一个可以使用`shared_from_this`的对象? 3. 除了`shared_from_this`,还有哪些方法可以在对象内部获取自身的`shared_ptr`? 4. `enable_shared_from_this`的内部实现原理是什么? 5. 在异步编程中,如何使用`shared_from_this`来延长对象的生命周期? </think> ### `shared_from_this` 指针详解 `shared_from_this` 是 C++ 中通过继承 `std::enable_shared_from_this<T>` 模板类获得的功能,用于在对象内部安全地获取指向自身的 `std::shared_ptr` 智能指针。以下是核心要点: #### 1. **基本用法** ```cpp #include <memory> class MyClass : public std::enable_shared_from_this<MyClass> { public: void func() { // 获取当前对象的共享指针 std::shared_ptr<MyClass> sp = shared_from_this(); // 安全使用sp(如传递到异步任务) } }; ``` #### 2. **核心限制** - **禁止在构造函数内调用** 对象的构造函数执行时,`shared_ptr` 尚未完成引用计数初始化(`weak_this_` 未就绪),调用会抛出 `std::bad_weak_ptr` 异常[^2][^5]。 ```cpp MyClass() { // 错误!构造未完成 auto sp = shared_from_this(); // ❌ 崩溃风险 } ``` - **必须由 `shared_ptr` 管理对象** 对象必须通过 `std::shared_ptr` 创建(如 `std::make_shared<MyClass>()`),栈对象或原始指针管理的对象无法使用此功能[^1][^3]。 #### 3. **典型错误场景** - **直接包装 `this` 指针** 手动用 `this` 创建多个独立的 `shared_ptr` 会导致重复释放: ```cpp struct Node { std::shared_ptr<Node> get_ptr() { return std::shared_ptr<Node>(this); // ❌ 多个独立控制块 } }; ``` 结果:同一内存被多个 `shared_ptr` 重复释放 → **未定义行为**(崩溃)[^4]。 #### 4. **安全替代方案** - **正确继承 `enable_shared_from_this`**: ```cpp struct SafeNode : public std::enable_shared_from_this<SafeNode> { std::shared_ptr<SafeNode> get_ptr() { return shared_from_this(); // ✅ 共享控制块 } }; ``` #### 5. **设计原则与最佳实践** - **统一使用智能指针**:避免混合原始指针与智能指针[^1]。 - **生命周期管理**:适用于异步回调、观察者模式等需延长对象生命周期的场景[^5]。 - **工厂模式创建对象**:强制通过 `shared_ptr` 创建实例: ```cpp static std::shared_ptr<MyClass> create() { return std::make_shared<MyClass>(); } ``` - **结合 `weak_ptr` 打破循环引用**:防止内存泄漏[^5]。 #### 6. **底层原理** `enable_shared_from_this` 内部维护一个 `std::weak_ptr<T> weak_this_` 成员。当对象被 `shared_ptr` 管理时,`shared_ptr` 的构造函数会初始化 `weak_this_`。调用 `shared_from_this()` 时,实际执行 `weak_this_.lock()` 返回共享所有权的 `shared_ptr`[^5]。 --- ### 常见问题解答 **Q1: 为什么构造函数中不能调用 `shared_from_this`?** A: 此时 `shared_ptr` 尚未初始化内部的 `weak_this_` 弱引用,无法安全生成 `shared_ptr`[^1][^2]。 **Q2: 如何返回指向当前对象的 `shared_ptr`?** A: 继承 `enable_shared_from_this` 并调用 `shared_from_this()`,且对象必须由 `shared_ptr` 管理[^3][^5]。 **Q3: 混合使用原始指针和智能指针有何风险?** A: 若原始指针被意外删除,通过 `shared_from_this` 获取的指针将引发未定义行为[^1][^4]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值