C++11新增的包装器详解
概述
C++11引入了许多新的特性,其中一个重要的特性是包装器。包装器是指能够包装任意类型的值,并且能够按照指定方式进行数据转换和操作的工具类。C++11中新增加的包装器主要有以下几个:
- std::shared_ptr: 表示一个共享所有权的指针,即多个指针指向同一个对象,在对象不被使用时自动释放。
- std::unique_ptr: 表示一个独享所有权的指针,可以删除被指向的对象。
- std::weak_ptr: 表示一个弱引用,指向一个可能已经被释放的对象,可以避免循环引用的问题。
- std::function: 表示一个可调用对象的封装器,允许将不同类型的可调用对象包装成统一的函数对象。
- std::tuple: 表示一个不同类型的序列,可以将多个不同类型的值组合成一个tuple,可以进行一些tuple特有的操作,如解包操作等。
本篇文章将对这几个包装器进行详细的讲解。
std::shared_ptr
std::shared_ptr是一个智能指针,用于对象的共享所有权。多个指针可以指向同一个对象,当最后一个使用指针离开作用域时,智能指针会自动释放所指向的对象。
以下是一个示例代码:
#include <iostream>
#include <memory>
class Foo {
public:
Foo() {
std::cout << "Foo constructor" << std::endl;
}
~Foo() {
std::cout << "Foo destructor" << std::endl;
}
};
int main() {
std::shared_ptr<Foo> ptr1(new Foo());
{
std::shared_ptr<Foo> ptr2(ptr1);
}
return 0;
}
输出结果为:
Foo constructor
Foo destructor
从输出结果可以看出,当最后一个使用指针ptr2离开作用域的时候,智能指针会自动释放所指向的对象。
std::unique_ptr
std::unique_ptr是一个独享所有权的智能指针,用于管理动态分配的对象。和std::shared_ptr不同,std::unique_ptr不支持多个指针指向同一个对象。
以下是一个示例:
#include <iostream>
#include <memory>
class Foo {
public:
Foo() {
std::cout << "Foo constructor" << std::endl;
}
~Foo() {
std::cout << "Foo destructor" << std::endl;
}
};
int main() {
std::unique_ptr<Foo> ptr1(new Foo());
std::unique_ptr<Foo> ptr2;
ptr2 = std::move(ptr1);
return 0;
}
输出结果为:
Foo constructor
Foo destructor
从输出结果可以看出,当ptr1被销毁时,智能指针会自动释放所指向的对象。如果没有使用std::move函数将ptr1的所有权转移给ptr2,那么程序将会报错,因为std::unique_ptr不支持多个指针指向同一个对象。
std::weak_ptr
std::weak_ptr也是一个智能指针,用于解决循环引用的问题。std::weak_ptr指向一个可能已经被释放的对象,它不改变对象的引用计数,不会防止对象被释放。在需要使用对象时,需要将std::weak_ptr转化成std::shared_ptr进行访问。
以下是一个示例:
#include <iostream>
#include <memory>
class B;
class A {
public:
std::weak_ptr<B> ptr;
A() {
std::cout << "A constructor" << std::endl;
}
~A() {
std::cout << "A destructor" << std::endl;
}
};
class B {
public:
std::shared_ptr<A> ptr;
B() {
std::cout << "B constructor" << std::endl;
}
~B() {
std::cout << "B destructor" << std::endl;
}
};
int main() {
std::shared_ptr<A> ptr1(new A());
std::shared_ptr<B> ptr2(new B());
ptr1->ptr = ptr2;
ptr2->ptr = ptr1;
return 0;
}
输出结果为:
A constructor
B constructor
从输出结果可以看出,当最后一个使用指针离开作用域时,智能指针会自动释放所指向的对象。如果没有使用std::weak_ptr将A和B之间的循环引用解除,程序将会发生内存泄漏。
std::function
std::function是一个用来封装不同类型可调用对象的类,可以将不同类型的可调用对象包装成统一的函数对象,从而可以在运行时动态地调用它们。
以下是一个示例:
#include <iostream>
#include <functional>
void print(int n) {
std::cout << "print: " << n << std::endl;
}
int main() {
std::function<void(int)> f = print;
f(123);
return 0;
}
输出结果为:
print: 123
从输出结果可以看出,将函数print封装到std::function对象f中,并使用f调用print函数。
std::tuple
std::tuple表示一个不同类型的序列,可以将多个不同类型的值组合成一个tuple,可以进行一些tuple特有的操作,如解包操作。
以下是一个示例:
#include <iostream>
#include <tuple>
int main() {
std::tuple<int, float, std::string> t(1, 2.0, "three");
std::cout << std::get<0>(t) << std::endl;
std::cout << std::get<1>(t) << std::endl;
std::cout << std::get<2>(t) << std::endl;
return 0;
}
输出结果为:
1
2
three
从输出结果可以看出,使用std::tuple定义了一个包含int、float和std::string类型的tuple变量t,使用std::get函数访问其中的元素。
结论
C++11中新增的包装器(std::shared_ptr、std::unique_ptr、std::weak_ptr、std::function、std::tuple)提供了更为方便和灵活的操作方式,可以使代码更加易读,易维护,并且更加安全。在具体的开发中,需要根据具体的业务场景和需求,选择合适的包装器进行使用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++11新增的包装器详解 - Python技术站