随性研究c++-智能指针

发布于:2025-04-05 ⋅ 阅读:(16) ⋅ 点赞:(0)

一、指针

就是随性研究一下,写个类

#pragma once
#include <memory>
#include<iostream>
/*shared_ptr 允许多个指针指向同一个对象,但是VoidPtr只能指向一个对象*/
/*unique_ptr 只能指向一个对象,不能被复制*/
/*weak_ptr 指向一个对象,但是不控制对象的生命周期,它是一个非 owning 指针,不能直接访问对象,弱引用*/
#pragma once
#include <memory>
#include<iostream>
/*shared_ptr 允许多个指针指向同一个对象,但是VoidPtr只能指向一个对象*/
/*unique_ptr 只能指向一个对象,不能被复制*/
/*weak_ptr 指向一个对象,但是不控制对象的生命周期,它是一个非 owning 指针,不能直接访问对象,弱引用*/
class VoidPtr
{
	std::shared_ptr<std::string> ptrstring=std::make_shared<std::string>();
	//加入三个初始化
	std::shared_ptr<int>p3=std::make_shared<int>(10);
	//p4指向是10个'9'
	std::shared_ptr<std::string>p4= std::make_shared<std::string>(10,'9');
	//默认为0
	std::shared_ptr<int>p5=std::make_shared<int>();
	//错误,必须直接初始化
	//std::shared_ptr<int>p6=new int(10);
	//正确,使用直接初始化
	//std::shared_ptr<int> p6(new int(10));
public:
	VoidPtr(std::string& p) :ptrstring(std::make_shared<std::string>(p)) {
		std::cout << "VoidPtr constructor" << std::endl;
	}
	 std::string  get()  { return *ptrstring; }
	 void  set(const std::string& p) { *ptrstring = p; }
	void print() {
		std::cout << "VoidPtr: " << get() << std::endl;
	}
	~VoidPtr() {
		std::cout << "VoidPtr destructor" << std::endl;
	}
	VoidPtr(const VoidPtr& other) = delete;
	std::shared_ptr<int> clone(int p) {
		return std::shared_ptr<int>(new int(p));
	}

	
};


写了一个私有标量 std::shared_ptrstd::string ptrstring;
Get和set去设置ptrstring,以及print,另外记录下destructor是时机

main函数调用
// c_TEST.cpp : 此文件包含 “main” 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include "VoidPtr.h"
int main()
{
  ;
   // 创建一个VoidPtr对象,传入一个初始字符串
  std::string initial_string = "Initial string";
  VoidPtr vp(initial_string);
  vp.print();

  // 使用get函数获取字符串并输出
  std::string retrieved = vp.get();
  std::cout << "Retrieved string: " << retrieved << std::endl;

  // 使用set函数修改字符串内容
  vp.set("Modified string");
  
  vp.print();
  std::string message = vp.get();
  std::cout << "Message: " << message << std::endl;
  std::shared_ptr<int> ptr(new int(10));//这个不能在类中实现

}

在 C++ 里,智能指针是用来管理动态分配内存的工具,能够自动处理内存的释放,防止内存泄漏。std::shared_ptrstd::unique_ptrstd::weak_ptr 是标准库中提供的三种智能指针,它们在所有权、引用计数和使用场景上存在差异。下面为你详细介绍:

1. std::unique_ptr

  • 特点
    • 独占所有权,同一时间内只允许一个 std::unique_ptr 指向某个对象。
    • 不能进行拷贝构造或赋值操作,但可以通过 std::move 转移所有权。
    • 对象在 std::unique_ptr 离开作用域时会被自动删除。
  • 应用场景:当你需要确保某个对象在任何时候只有一个所有者时,可使用 std::unique_ptr。例如,管理动态分配的资源(像文件句柄、网络连接)。
  • 例程
#include <iostream>
#include <memory>

// 定义一个简单的类
class MyClass {
public:
    MyClass() { std::cout << "MyClass 构造函数" << std::endl; }
    ~MyClass() { std::cout << "MyClass 析构函数" << std::endl; }
    void doSomething() { std::cout << "MyClass 正在执行操作" << std::endl; }
};

int main() {
    // 创建一个 unique_ptr 并指向一个新的 MyClass 对象
    std::unique_ptr<MyClass> uniquePtr = std::make_unique<MyClass>();

    // 调用对象的成员函数
    uniquePtr->doSomething();

    // 转移所有权
    std::unique_ptr<MyClass> anotherUniquePtr = std::move(uniquePtr);
    if (uniquePtr == nullptr) {
        std::cout << "uniquePtr 现在为空" << std::endl;
    }
    anotherUniquePtr->doSomething();

    // 当 anotherUniquePtr 离开作用域时,对象会被自动删除
    return 0;
}

2. std::shared_ptr

  • 特点
    • 共享所有权,多个 std::shared_ptr 可以指向同一个对象。
    • 采用引用计数机制,每增加一个指向该对象的 std::shared_ptr,引用计数就加 1;每减少一个,引用计数就减 1。
    • 当引用计数变为 0 时,对象会被自动删除。
  • 应用场景:当多个部分的代码需要访问同一个对象,且无法确定哪个部分最后使用该对象时,适合使用 std::shared_ptr。例如,在图形处理中,多个图形元素可能共享同一块纹理数据。
  • 例程
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "MyClass 构造函数" << std::endl; }
    ~MyClass() { std::cout << "MyClass 析构函数" << std::endl; }
    void doSomething() { std::cout << "MyClass 正在执行操作" << std::endl; }
};

int main() {
    // 创建一个 shared_ptr 并指向一个新的 MyClass 对象
    std::shared_ptr<MyClass> sharedPtr1 = std::make_shared<MyClass>();
    std::cout << "引用计数: " << sharedPtr1.use_count() << std::endl;

    // 创建另一个 shared_ptr 并共享同一个对象
    std::shared_ptr<MyClass> sharedPtr2 = sharedPtr1;
    std::cout << "引用计数: " << sharedPtr1.use_count() << std::endl;

    // 调用对象的成员函数
    sharedPtr2->doSomething();

    // 当所有 shared_ptr 离开作用域时,对象会被自动删除
    return 0;
}

3. std::weak_ptr

  • 特点
    • 不拥有对象,是对 std::shared_ptr 管理对象的一种弱引用。
    • 不会增加引用计数,所以不会影响对象的生命周期。
    • 可以通过 lock() 方法获取一个 std::shared_ptr,用于访问对象。若对象已被删除,lock() 会返回一个空的 std::shared_ptr
  • 应用场景:当你需要解决 std::shared_ptr 循环引用问题,或者在不影响对象生命周期的情况下观察对象时,可使用 std::weak_ptr。例如,在实现缓存机制时,使用 std::weak_ptr 来引用缓存对象,避免影响对象的正常释放。
  • 例程
#include <iostream>
#include <memory>

class B;

class A {
public:
    std::shared_ptr<B> bPtr;
    ~A() { std::cout << "A 析构函数" << std::endl; }
};

class B {
public:
    std::weak_ptr<A> aPtr; // 使用 weak_ptr 避免循环引用
    ~B() { std::cout << "B 析构函数" << std::endl; }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    a->bPtr = b;
    b->aPtr = a;

    // 使用 weak_ptr 访问对象
    if (auto sharedA = b->aPtr.lock()) {
        std::cout << "成功通过 weak_ptr 访问 A 对象" << std::endl;
    }

    // 当 a 和 b 离开作用域时,对象会被正确删除
    return 0;
}

总结

  • std::unique_ptr:适用于独占所有权的场景,确保对象在任何时候只有一个所有者。
  • std::shared_ptr:适用于共享所有权的场景,多个指针可以共享同一个对象。
  • std::weak_ptr:适用于解决循环引用问题,或者在不影响对象生命周期的情况下观察对象。