C++11 新特性——智能指针使用详解
在C++中,内存管理一直是一个非常重要的事情,一个常见的错误就是忘记释放先前分配的内存。C++11引入了智能指针,从而使得内存管理更加方便。本文将详细介绍智能指针的使用方法。
智能指针概述
C++中的智能指针是一种RAII(Resource Acquisition Is Initialization)机制的实现,它通过对象生命周期的结束来自动释放分配的内存。
在C++11中,常见的智能指针有两种:std::unique_ptr和std::shared_ptr。下面将分别详细说明它们的用法。
std::unique_ptr
std::unique_ptr是一种独占所有权的智能指针。它保证同时只有一个指针可以指向被分配的内存,并且在它被销毁时会自动释放这个内存,即可以避免内存泄漏。
unique_ptr的定义和初始化
std::unique_ptr的定义样式如下:
std::unique_ptr<type> ptr_name(new type(args));
其中,type为要分配内存的类型,ptr_name为指向该类型对象的智能指针,new type(args)用于分配堆内存并返回该堆内存的地址。
下面是一个示例:
std::unique_ptr<int> p(new int(10));
这个语句创建了一个指向int类型对象的智能指针p,并将值为10的整数存放在指针指向的内存位置。
unique_ptr的拷贝和移动
由于std::unique_ptr是独占所有权的,因此它不能被其他指针指向。但是,我们可以使用std::move函数将其转移给另一个unique_ptr。如下所示:
std::unique_ptr<int> p1(new int(10));
std::unique_ptr<int> p2(std::move(p1));
这个语句创建了两个指向int类型对象的智能指针p1和p2,其中p2是通过std::move函数从p1转移而来的。
值得注意的是,由于唯一所有权,std::unique_ptr是不能被拷贝的。以下代码会导致编译错误:
std::unique_ptr<int> p1(new int(10));
std::unique_ptr<int> p2(p1); // 编译错误
unique_ptr的使用
std::unique_ptr的使用方法与普通指针类似,可以使用*或->操作符来访问其所指向的对象,如下所示:
std::unique_ptr<int> p(new int(10));
std::cout << *p << std::endl;
这个语句输出p指向的int类型对象的值,即10。
除此之外,std::unique_ptr还提供了release函数和reset函数。
release函数用于将std::unique_ptr中的指针地址返回并释放所有权。下面是一个示例:
std::unique_ptr<int> p(new int(10));
int* ptr = p.release();
这个语句将p中的指针地址释放,并将其返回给变量ptr。
reset函数用于释放当前指向的对象,并将指针指向新对象。下面是一个示例:
std::unique_ptr<int> p(new int(10));
p.reset(new int(20));
std::cout << *p << std::endl;
这个语句释放p指向的int类型对象,并将p指向一个新的地址,该地址存放了值为20的整数。
std::shared_ptr
std::shared_ptr是一种共享所有权的智能指针。它可以使多个指针指向同一块内存,并可以在最后一个指针被销毁时自动释放该内存,避免了内存泄露。
shared_ptr的定义和初始化
std::shared_ptr的定义样式如下:
std::shared_ptr<type> ptr_name(new type(args));
其中,type为要分配内存的类型,ptr_name为指向该类型对象的智能指针,new type(args)用于分配堆内存并返回该堆内存的地址。
下面是一个示例:
std::shared_ptr<int> p1(new int(10));
std::shared_ptr<int> p2 = p1; // p2和p1共享所有权
这个语句创建了两个指向int类型对象的智能指针p1和p2,其中p2是从p1拷贝而来的。由于std::shared_ptr是共享所有权的,因此p1和p2指向同一个int类型对象,并且在这两个指针被销毁时,它们会自动释放该内存。
shared_ptr的使用
std::shared_ptr的使用方法与普通指针类似,可以使用*或->操作符来访问其所指向的对象,如下所示:
std::shared_ptr<int> p(new int(10));
std::cout << *p << std::endl;
这个语句输出p指向的int类型对象的值,即10。
除此之外,std::shared_ptr还提供了一个use_count函数,用于返回当前有多少个智能指针指向该对象。下面是一个示例:
std::shared_ptr<int> p1(new int(10));
std::shared_ptr<int> p2 = p1;
std::cout << "The use count is " << p1.use_count() << std::endl; // 输出2
这个语句输出指向int类型对象的智能指针的个数,即2。
示例
下面是一个使用std::unique_ptr的示例,用于分配包含两个字符串的结构。
struct test
{
std::string str1;
std::string str2;
test() : str1(""), str2("") { }
test(const std::string& s1, const std::string& s2) : str1(s1), str2(s2) { }
};
int main()
{
std::unique_ptr<test> ptest(new test("Hello", "world"));
std::cout << ptest->str1 << ", " << ptest->str2 << std::endl;
return 0;
}
这段代码首先定义了一个结构体test,其包含两个string类型的成员变量str1和str2。然后,通过std::unique_ptr分配一个test类型的对象,其中使用了结构体构造函数初始化了它的两个成员变量。最后,通过unique_ptr的->操作符访问了该结构体的成员变量,并将它们输出到终端上。
下面是一个使用std::shared_ptr的示例,用于模拟对象间的引用:
#include <iostream>
#include <memory>
class test;
void func(std::shared_ptr<test> p);
class test
{
public:
test() { std::cout << "test is constructed" << std::endl; }
~test() { std::cout << "test is destructed" << std::endl; }
void func(std::shared_ptr<test> p)
{
std::cout << "test's func is called" << std::endl;
}
};
void func(std::shared_ptr<test> p)
{
std::cout << "func is called" << std::endl;
p->func(p);
}
int main()
{
std::shared_ptr<test> p1(new test());
func(p1);
return 0;
}
这个代码模拟了两个对象,它们之间相互引用。该示例中,通过std::shared_ptr分配了一个test类型的对象,并将其传递给func函数。在func函数中,使用std::shared_ptr调用了test类的成员函数func,并将该智能指针作为参数传递给了该函数。
在这个示例中,由于使用了std::shared_ptr,因此两个对象之间的引用始终保持着,并且在所有引用被销毁时,它们指向的内存会被自动释放,从而避免了内存泄漏。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++11 新特性——智能指针使用详解 - Python技术站