一、指针
就是随性研究一下,写个类
#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_ptr
、std::unique_ptr
和 std::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
:适用于解决循环引用问题,或者在不影响对象生命周期的情况下观察对象。