编程笔记 - C++ 智能指针与引用
在 C 语言编程中,使用裸指针(raw pointer)几乎是处理动态内存的唯一方式。然而,随着 C++ 的不断演进,特别是在 C++11 及之后的标准中,智能指针(std::unique_ptr, std::shared_ptr, std::weak_ptr)和引用(&)成为了更安全、更现代的替代品。
使用 C 风格指针的风险
C 风格的指针虽然灵活,但也伴随着许多问题:
- 内存泄漏:每一个
new必须对应一个delete,不小心忘记释放就可能导致内存泄漏。 - 空指针:在释放指针后继续访问,会引发未定义行为。
- 野指针:未初始化的指针可能指向随机内存。
使用 C++ 智能指针
智能指针是一种模板类,封装了动态分配对象的指针,并在其生命周期结束时自动释放资源。
-
内存自动释放
std::unique_ptr在析构时自动调用delete;std::shared_ptr通过引用计数管理生命周期。 -
异常安全
在栈上管理智能指针,无论函数怎样退出,析构都会正确执行,不用手动释放。 -
所有权语义清晰
-
std::unique_ptr<T>:独占所有权,不可复制,仅可移动。void foo() { std::unique_ptr<int> up(new int(100)); *up += 1; // auto up2 = up; // Error: Not duplicable. auto up2 = std::move(up); // OK: Pass ownership. } -
std::shared_ptr<T>:共享所有权,内部引用计数;当最后一个shared_ptr销毁时释放资源。void foo() { std::shared_ptr<int> sp1 = std::make_shared<int>(200); { std::shared_ptr<int> sp2 = sp1; // Reference count +1. std::cout << *sp2 << "\n"; } // sp2 leaves the scope, reference count -1. // When the last sp leaves the scope, the delete operator is called automatically. } -
std::weak_ptr<T>:配合shared_ptr使用,不影响引用计数,可安全检测对象是否已销毁。void foo() { std::shared_ptr<int> sp(new int(10)); std::weak_ptr<int> wp(sp); std::cout << wp.use_count() << std::endl; // wp does not increase reference count. std::cout << *(wp.lock()) << std::endl; // Access the object pointed by sp }
-
函数传参时应传递引用以代替传递指针
在 C++ 编程中,如果函数中仅仅想使用对象内的资源,那么应该向函数传递引用而不是传递智能指针,因为函数内不需要智能指针声明周期的相关语义。
void process(int& value) {
// value will always be ready.
value += 10;
}
int main() {
int x = 5;
process(x); // OK
// process(nullptr); // Error: null pointer.
}
易混淆的点:智能指针与引用结合
| Function signature | Semantic | Rule |
|---|---|---|
func(std::unique_ptr<Widget>) |
func takes ownership | R.32 |
func(std::unique_ptr<Widget>&) |
func meant to reseat Widget | R.33 |
func(std::shared_ptr<Widget>) |
func shares ownership | R.34 |
func(std::shared_ptr<Widget>&) |
func might reseat Widget | R.35 |
func(const std::shared_ptr<Widget>&) |
func might retain a reference count | R.36 |

浙公网安备 33010602011771号