【C\C++】C++11 智能指针所有使用场景及实例代码

线程间应用

  1. 使用 std::unique_ptr 管理动态分配的对象,并在多个线程中共享:
class MyObject {
public:
    void doSomething() {
        // ...
    }
};

void threadFunc(std::unique_ptr<MyObject> obj) {
    obj->doSomething();
}

int main() {
    std::unique_ptr<MyObject> obj(new MyObject());
    std::thread t1(threadFunc, std::move(obj));
    std::thread t2(threadFunc, std::move(obj));
    t1.join();
    t2.join();
    // obj会在离开作用域时自动释放内存
    return 0;
}

在这个例子中,MyObject 对象被动态分配,并使用 std::unique_ptr 管理其生命周期。然后,两个线程分别使用 std::movestd::unique_ptr 转移给线程函数 threadFunc,并在函数中使用对象。由于 std::unique_ptr 是独占所有权的智能指针,因此在转移后,原始的 std::unique_ptr 将不再拥有对象的所有权(这里是直接夺权了吗?如何证明 t2 夺取了 t1 的独占式智能指针的使用权),避免了多个线程同时访问同一个对象的问题。(那如果后续t1又要使用,会夺取回去吗?)

  1. 使用 std::shared_ptr 管理动态分配的对象,并在多个线程中共享:
class MyObject {
public:
    void doSomething() {
        // ...
    }
};

void threadFunc(std::shared_ptr<MyObject> obj) {
    obj->doSomething();
}

int main() {
    std::shared_ptr<MyObject> obj(new MyObject());
    std::thread t1(threadFunc, obj);
    std::thread t2(threadFunc, obj);
    t1.join();
    t2.join();
    // obj会在离开作用域时自动释放内存
    return 0;
}

在这个例子中,MyObject 对象被动态分配,并使用 std::shared_ptr 管理其生命周期。然后,两个线程分别使用 std::shared_ptr 共享对象,并在函数中使用对象。由于 std::shared_ptr 是共享所有权的智能指针,因此多个线程可以同时访问同一个对象,由智能指针来管理对象的生命周期,避免了多个线程同时访问或释放同一个对象的问题。(如何使用 gdb 确认当前智能共享指针引用计数)

这些例子展示了智能指针的更复杂的用法,包括在多线程编程中共享资源、使用独占所有权和共享所有权的智能指针等。智能指针是一种非常有用的C++语言特性,可以提高程序的健壮性和可维护性。

类内应用

以下是更复杂的例子,展示了智能指针的使用场景:

  1. 使用 std::unique_ptr 管理动态分配的对象,并在类中使用:
class MyClass {
public:
    MyClass(std::unique_ptr<MyObject> obj) : m_obj(std::move(obj)) {}
private:
    std::unique_ptr<MyObject> m_obj;
};

int main() {
    std::unique_ptr<MyObject> obj(new MyObject());
    MyClass myClass(std::move(obj));
    // obj会在离开作用域时自动释放内存
    return 0;
}

在这个例子中,MyObject 对象被动态分配,并使用 std::unique_ptr 管理其生命周期。然后,std::unique_ptr 被转移给类 MyClass 的成员变量 m_obj,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。

  1. 使用 std::shared_ptr 管理动态分配的对象,并在类中使用:
class MyClass {
public:
    MyClass(std::shared_ptr<MyObject> obj) : m_obj(obj) {}
private:
    std::shared_ptr<MyObject> m_obj;
};

int main() {
    std::shared_ptr<MyObject> obj(new MyObject());
    MyClass myClass(obj);
    // obj会在离开作用域时自动释放内存
    return 0;
}

在这个例子中,MyObject 对象被动态分配,并使用 std::shared_ptr 管理其生命周期。然后,std::shared_ptr 被传递给类 MyClass 的成员变量 m_obj,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。

  1. 使用 std::unique_ptr 管理动态分配的对象,并在容器中存储:
std::vector<std::unique_ptr<MyObject>> vec;
vec.push_back(std::unique_ptr<MyObject>(new MyObject()));
// vec会在离开作用域时自动释放内存

在这个例子中,MyObject 对象被动态分配,并使用 std::unique_ptr 管理其生命周期。然后,std::unique_ptr 被转移给容器 std::vector,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。

  1. 使用 std::shared_ptr 管理动态分配的对象,并在容器中存储:
std::vector<std::shared_ptr<MyObject>> vec;
vec.push_back(std::shared_ptr<MyObject>(new MyObject()));
// vec会在离开作用域时自动释放内存

在这个例子中,MyObject 对象被动态分配,并使用 std::shared_ptr 管理其生命周期。然后,std::shared_ptr 被传递给容器 std::vector,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。

这些例子展示了智能指针的更复杂的用法,包括在类中使用、在容器中存储等。

异常场景应用

以下是更复杂的例子,展示了智能指针的使用场景:

  1. 使用 std::unique_ptr 管理动态分配的对象,并在异常发生时自动释放内存:
void foo() {
    std::unique_ptr<MyObject> obj(new MyObject());
    // do some operations on obj
    if (someCondition) {
        throw std::runtime_error("something went wrong");
    }
    // obj会在离开作用域时自动释放内存
}

int main() {
    try {
        foo();
    } catch (const std::exception& e) {
        // handle exception
    }
    return 0;
}

在这个例子中,MyObject 对象被动态分配,并使用 std::unique_ptr 管理其生命周期。然后,在函数 foo 中进行一些操作,如果发生异常,则会在函数退出时自动释放内存,避免了内存泄漏的问题。

  1. 使用 std::shared_ptr 管理动态分配的对象,并在异常发生时自动释放内存:
void foo() {
    std::shared_ptr<MyObject> obj(new MyObject());
    // do some operations on obj
    if (someCondition) {
        throw std::runtime_error("something went wrong");
    }
    // obj会在离开作用域时自动释放内存
}

int main() {
    try {
        foo();
    } catch (const std::exception& e) {
        // handle exception
    }
    return 0;
}

在这个例子中,MyObject 对象被动态分配,并使用 std::shared_ptr 管理其生命周期。然后,在函数 foo 中进行一些操作,如果发生异常,则会在函数退出时自动释放内存,避免了内存泄漏的问题。

  1. 使用 std::weak_ptr 避免循环引用:
class B;

class A {
public:
    void setB(std::shared_ptr<B> b) {
        m_b = b;
    }
private:
    std::weak_ptr<B> m_b;
};

class B {
public:
    void setA(std::shared_ptr<A> a) {
        m_a = a;
    }
private:
    std::weak_ptr<A> m_a;
};

int main() {
    std::shared_ptr<A> a(new A());
    std::shared_ptr<B> b(new B());
    a->setB(b);
    b->setA(a);
    // a和b会在离开作用域时自动释放内存,避免循环引用导致的内存泄漏
    return 0;
}

在这个例子中,类 AB 互相引用,如果使用 std::shared_ptr 相互持有,会导致循环引用,从而导致内存泄漏。为了避免这个问题,可以使用 std::weak_ptr 来解决循环引用的问题,避免内存泄漏。

这些例子展示了智能指针的更复杂的用法,包括异常安全、避免循环引用等。

结合 Lambda 表达式的应用

  1. 使用 std::unique_ptr 管理动态分配的对象,并在lambda表达式中使用:
std::unique_ptr<MyObject> obj(new MyObject());
auto lambda = [ptr = std::move(obj)]() {
    // do some operations on ptr
};
// obj会在离开作用域时自动释放内存

在这个例子中,MyObject 对象被动态分配,并使用 std::unique_ptr 管理其生命周期。然后,使用 std::movestd::unique_ptr 转移给lambda表达式,并在表达式中使用对象。由于 std::unique_ptr 是独占所有权的智能指针,因此在转移后,原始的 std::unique_ptr 将不再拥有对象的所有权,避免了手动释放内存的问题。

  1. 使用 std::shared_ptr 管理动态分配的对象,并在lambda表达式中使用:
std::shared_ptr<MyObject> obj(new MyObject());
auto lambda = [ptr = obj]() {
    // do some operations on ptr
};
// obj会在离开作用域时自动释放内存

在这个例子中,MyObject 对象被动态分配,并使用 std::shared_ptr 管理其生命周期。然后,使用 std::shared_ptr 传递给lambda表达式,并在表达式中使用对象。由于 std::shared_ptr 是共享所有权的智能指针,因此多个lambda表达式可以同时访问同一个对象,由智能指针来管理对象的生命周期,避免了多个lambda表达式同时访问或释放同一个对象的问题。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11引入了智能指针,它们是一种用于管理动态分配的内存的工具。智能指针可以自动处理内存的释放,避免了手动释放内存的麻烦和可能的内存泄漏。C++11提供了三种类型的智能指针:unique_ptr、shared_ptr和weak_ptr。 1. unique_ptr:unique_ptr是一种独占所有权的智能指针,它确保只有一个指针可以访问给定的资源。当unique_ptr超出作用域或被重新赋值时,它会自动释放所管理的资源。以下是一个unique_ptr的示例: ```cpp #include <memory> int main() { std::unique_ptr<int> ptr(new int(10)); // 使用ptr指向的资源 std::cout << *ptr << std::endl; // unique_ptr会在超出作用域时自动释放资源 return 0; } ``` 2. shared_ptr:shared_ptr是一种共享所有权的智能指针,它可以被多个指针同时访问同一个资源。shared_ptr使用引用计数来跟踪资源的使用情况,当最后一个shared_ptr超出作用域时,资源会被释放。以下是一个shared_ptr的示例: ```cpp #include <memory> int main() { std::shared_ptr<int> ptr1(new int(10)); std::shared_ptr<int> ptr2 = ptr1; // 使用ptr1或ptr2指向的资源 std::cout << *ptr1 << std::endl; std::cout << *ptr2 << std::endl; // shared_ptr会在最后一个引用超出作用域时释放资源 return 0; } ``` 3. weak_ptr:weak_ptr是一种弱引用的智能指针,它可以指向shared_ptr所管理的资源,但不会增加引用计数。weak_ptr主要用于解决shared_ptr的循环引用问题。以下是一个weak_ptr的示例: ```cpp #include <memory> int main() { std::shared_ptr<int> ptr1(new int(10)); std::weak_ptr<int> ptr2 = ptr1; // 使用ptr1或ptr2指向的资源 std::cout << *ptr1 << std::endl; if (auto sharedPtr = ptr2.lock()) { // 使用ptr2指向的资源 std::cout << *sharedPtr << std::endl; } // weak_ptr不会影响资源的生命周期 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值