我有以下类模板示例:
template<class T>
class MyContainer{
public:
T* myArray;
int size;
MyContainer(int n) : size(n){
myArray = new T[n];
}
~MyContainer(){
delete[] myArray;
}
};
是否可以为 myArray 使用 unique_ptr 或 shared_ptr 等智能指针,这样我就不需要在析构函数中释放它?如何?
是的,你可以,而且你真的应该:
template<class T>
class MyContainer{
public:
std::unique_ptr<T[]> myArray;
int size;
MyContainer(int n) : myArray(new T[n]), size(n) { }
};
int main() {
MyContainer<int> c(10);
}
或者,如果可能,将大小作为模板参数传递:
template<class T, std::size_t N>
class MyContainer{
public:
std::unique_ptr<T[]> myArray;
int size = N;
MyContainer() : myArray(new T[N]) { }
};
int main() {
MyContainer<int, 10> c;
}
或者,如果可能,只需使用std::vector<>
或std::array<>
笔记:
- 可变长度数组是非标准的。
- 应按声明顺序初始化类成员。
- 大小应为
unsigned
(std::size_t
(
template<class T>
class MyContainer{
public:
unique_ptr<T[]> myArray;
int size;
MyContainer(int n) : size(n), myArray(new T[n]) {}
};
智能指针必须使用数组释放器,否则它是 UB,尽管在普通类型的情况下可能是相同的代码。
在这里查看整个std::unique_ptr
界面。
你不仅可以,而且你真的应该这样做。程序员经常惊讶地发现,如果构造函数引发异常(这是指示由于任何原因无法创建对象的推荐方法(,析构函数不会运行,因为编译器没有通用方法来知道析构函数中的哪些行对应于构造函数中的哪些行。
另一方面,任何已创建的对象都会被销毁,因为有一种通用方法可以知道哪些对象需要销毁。 换句话说,如果你的对象有两个原始指针,并且第一次调用new
成功,但第二次失败,则析构函数将不会运行,并且第一个指针永远不会delete
d。但是,如果你的对象有两个智能指针,第一个成功构造,第二个失败,第一个智能指针将被正确销毁,你不必担心它。