智能指针本质上是原始指针的一种包装,它们自动管理内存,避免内存泄漏和悬空指针问题。C++11引入了三种主要的智能指针:unique_ptr、shared_ptr和weak_ptr。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include <iostream>
#include <memory>
class Entity
{
public:
Entity() { std::cout << "Create Entity!" << std::endl; }
~Entity() { std::cout << "Destroy Entity!" << std::endl; }
void Print() { std::cout << "Hello!" << std::endl; }
};
int main()
{
// 传统的原始指针(不推荐)
Entity* rawPtr = new Entity();
rawPtr->Print();
delete rawPtr; // 容易忘记,导致内存泄漏
// 使用智能指针(推荐)
{
auto smartPtr = std::make_unique<Entity>();
smartPtr->Print();
// 离开作用域时自动删除,无需手动delete
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <memory>
int main()
{
{
// 创建unique_ptr的两种方式
std::unique_ptr<Entity> uniqueEntity1(new Entity()); // 不推荐
std::unique_ptr<Entity> uniqueEntity2 = std::make_unique<Entity>(); // 推荐,更安全
uniqueEntity2->Print();
// unique_ptr是唯一的,不能复制
// std::unique_ptr<Entity> copy = uniqueEntity2; // 编译错误
// 但可以移动
std::unique_ptr<Entity> moved = std::move(uniqueEntity2);
// 现在uniqueEntity2为空,moved拥有对象
if (uniqueEntity2 == nullptr)
std::cout << "uniqueEntity2 is now null" << std::endl;
moved->Print();
} // moved离开作用域,Entity自动销毁
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
class Resource
{
private:
std::string m_Name;
public:
Resource(const std::string& name) : m_Name(name)
{
std::cout << "Create resource: " << m_Name << std::endl;
}
~Resource()
{
std::cout << "Destroy resource: " << m_Name << std::endl;
}
void Use() const
{
std::cout << "Using resource: " << m_Name << std::endl;
}
};
// 工厂函数返回unique_ptr
std::unique_ptr<Resource> CreateResource(const std::string& name)
{
return std::make_unique<Resource>(name);
}
// 函数接受unique_ptr参数(转移所有权)
void ProcessResource(std::unique_ptr<Resource> resource)
{
resource->Use();
// 函数结束时resource被销毁
}
// 函数接受引用(不转移所有权)
void UseResource(const Resource& resource)
{
resource.Use();
}
int main()
{
auto resource1 = CreateResource("Resource1");
UseResource(*resource1); // 传递引用,不转移所有权
auto resource2 = CreateResource("Resource2");
ProcessResource(std::move(resource2)); // 转移所有权
// resource2现在为空
if (!resource2)
std::cout << "resource2 is null after move" << std::endl;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
int main()
{
std::shared_ptr<Entity> sharedEntity2;
{
// 创建shared_ptr
std::shared_ptr<Entity> sharedEntity1 = std::make_shared<Entity>(); // 推荐,有更小的开销
// std::shared_ptr<Entity> sharedEntity1(new Entity()); // 也可以,但开销更大
sharedEntity2 = sharedEntity1; // shared_ptr可以复制,内部维护一个引用计数
std::cout << "Reference count: " << sharedEntity1.use_count() << std::endl; // 输出: 2
{
std::shared_ptr<Entity> sharedEntity3 = sharedEntity1;
std::cout << "Reference count: " << sharedEntity1.use_count() << std::endl; // 输出: 3
} // sharedEntity3销毁,引用计数减1
std::cout << "Reference count: " << sharedEntity1.use_count() << std::endl; // 输出: 2
} // sharedEntity1销毁,引用计数减1
std::cout << "Reference count: " << sharedEntity2.use_count() << std::endl; // 输出: 1
sharedEntity2->Print();
} // sharedEntity2销毁,引用计数变为0,Entity被删除
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
class Player
{
private:
std::string m_Name;
public:
Player(const std::string& name) : m_Name(name)
{
std::cout << "Create player: " << m_Name << std::endl;
}
~Player()
{
std::cout << "Destroy player: " << m_Name << std::endl;
}
const std::string& GetName() const { return m_Name; }
};
class Team
{
private:
std::vector<std::shared_ptr<Player>> m_Players;
std::string m_Name;
public:
Team(const std::string& name) : m_Name(name) {}
void AddPlayer(std::shared_ptr<Player> player)
{
m_Players.push_back(player);
std::cout << player->GetName() << " joined team " << m_Name << std::endl;
}
void RemovePlayer(const std::string& playerName)
{
auto it = std::find_if(m_Players.begin(), m_Players.end(),
[&playerName](const std::shared_ptr<Player>& player) {
return player->GetName() == playerName;
});
if (it != m_Players.end())
{
std::cout << (*it)->GetName() << " left team " << m_Name << std::endl;
m_Players.erase(it);
}
}
void ListPlayers() const
{
std::cout << "Team " << m_Name << " players:" << std::endl;
for (const auto& player : m_Players)
{
std::cout << " - " << player->GetName()
<< " (refs: " << player.use_count() << ")" << std::endl;
}
}
};
int main()
{
auto player1 = std::make_shared<Player>("Alice");
auto player2 = std::make_shared<Player>("Bob");
{
Team teamA("Red Team");
Team teamB("Blue Team");
teamA.AddPlayer(player1);
teamA.AddPlayer(player2);
teamB.AddPlayer(player1); // player1同时在两个队伍中
teamA.ListPlayers();
teamB.ListPlayers();
teamA.RemovePlayer("Alice");
std::cout << "After removing Alice from Red Team:" << std::endl;
teamB.ListPlayers(); // Alice仍在Blue Team中
} // 队伍销毁,但玩家对象可能仍然存在
std::cout << "Teams destroyed, player1 refs: " << player1.use_count() << std::endl;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
int main()
{
std::weak_ptr<Entity> weakEntity;
{
std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
weakEntity = sharedEntity; // weak_ptr不会增加引用计数
std::cout << "shared_ptr count: " << sharedEntity.use_count() << std::endl; // 输出: 1
std::cout << "weak_ptr expired: " << weakEntity.expired() << std::endl; // 输出: false
// 从weak_ptr获取shared_ptr
if (auto shared = weakEntity.lock())
{
shared->Print();
std::cout << "Successfully accessed object through weak_ptr" << std::endl;
}
} // sharedEntity销毁,Entity被删除
std::cout << "weak_ptr expired: " << weakEntity.expired() << std::endl; // 输出: true
// 尝试从已过期的weak_ptr获取shared_ptr
if (auto shared = weakEntity.lock())
{
shared->Print();
}
else
{
std::cout << "Entity has been destroyed, cannot access through weak_ptr" << std::endl;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
class Child;
class Parent
{
private:
std::vector<std::shared_ptr<Child>> m_Children;
std::string m_Name;
public:
Parent(const std::string& name) : m_Name(name)
{
std::cout << "Create parent: " << m_Name << std::endl;
}
~Parent()
{
std::cout << "Destroy parent: " << m_Name << std::endl;
}
void AddChild(std::shared_ptr<Child> child);
const std::string& GetName() const { return m_Name; }
};
class Child
{
private:
std::weak_ptr<Parent> m_Parent; // 使用weak_ptr避免循环引用
std::string m_Name;
public:
Child(const std::string& name) : m_Name(name)
{
std::cout << "Create child: " << m_Name << std::endl;
}
~Child()
{
std::cout << "Destroy child: " << m_Name << std::endl;
}
void SetParent(std::shared_ptr<Parent> parent)
{
m_Parent = parent;
}
void CallParent()
{
if (auto parent = m_Parent.lock())
{
std::cout << m_Name << " calling parent " << parent->GetName() << std::endl;
}
else
{
std::cout << m_Name << "'s parent is no longer available" << std::endl;
}
}
const std::string& GetName() const { return m_Name; }
};
void Parent::AddChild(std::shared_ptr<Child> child)
{
m_Children.push_back(child);
child->SetParent(shared_from_this()); // 需要继承std::enable_shared_from_this
}
// 修正版本的Parent类
class BetterParent : public std::enable_shared_from_this<BetterParent>
{
private:
std::vector<std::shared_ptr<Child>> m_Children;
std::string m_Name;
public:
BetterParent(const std::string& name) : m_Name(name)
{
std::cout << "Create parent: " << m_Name << std::endl;
}
~BetterParent()
{
std::cout << "Destroy parent: " << m_Name << std::endl;
}
void AddChild(std::shared_ptr<Child> child)
{
m_Children.push_back(child);
child->SetParent(shared_from_this());
}
const std::string& GetName() const { return m_Name; }
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
class FileHandle
{
private:
FILE* m_File;
std::string m_Filename;
public:
FileHandle(const std::string& filename) : m_Filename(filename)
{
m_File = fopen(filename.c_str(), "w");
if (m_File)
std::cout << "Opened file: " << filename << std::endl;
}
~FileHandle()
{
if (m_File)
{
fclose(m_File);
std::cout << "Closed file: " << m_Filename << std::endl;
}
}
FILE* Get() const { return m_File; }
};
int main()
{
// 使用自定义删除器
auto filePtr = std::unique_ptr<FileHandle, std::function<void(FileHandle*)>>(
new FileHandle("test.txt"),
[](FileHandle* f) {
std::cout << "Custom deleter called" << std::endl;
delete f;
}
);
// 或者使用shared_ptr的自定义删除器
auto sharedFile = std::shared_ptr<FileHandle>(
new FileHandle("shared_test.txt"),
[](FileHandle* f) {
std::cout << "Shared custom deleter called" << std::endl;
delete f;
}
);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// make_shared vs shared_ptr(new T)
void PerformanceComparison()
{
// 方式1:make_shared(推荐)
// 只进行一次内存分配,对象和控制块在同一块内存中
auto ptr1 = std::make_shared<Entity>();
// 方式2:shared_ptr(new T)
// 进行两次内存分配,对象和控制块分开
std::shared_ptr<Entity> ptr2(new Entity());
// make_shared更高效,但在某些情况下可能延迟内存释放
}
|
- 智能指针本质:原始指针的一种包装,自动管理内存
- unique_ptr:独占所有权指针,不能复制但可以移动,销毁时自动删除对象
- shared_ptr:共享所有权指针,内部维护引用计数,引用计数为0时自动删除对象
- weak_ptr:弱引用指针,与shared_ptr一起使用,不影响引用计数,主要用于解决循环引用问题
- 最佳实践:优先使用make_unique和make_shared,避免直接使用new