我有以下类模板示例:
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等智能指针,因此我不需要在析构函数中释放它?怎么样?
答案 0 :(得分:3)
是的,你可以,你真的应该:
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
)答案 1 :(得分:2)
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
界面。
答案 2 :(得分:1)
你不仅可以,而且你真的应该这样做。程序员经常会惊讶地发现,如果构造函数抛出异常(这是建议的方式来表示无法以任何理由创建对象),析构函数不会运行,因为没有编译器知道析构函数中的哪些行对应于构造函数中的哪些行的一般方法。
另一方面,任何已创建的对象都被销毁,因为有一般方法可以知道哪些对象需要销毁。换句话说,如果你的对象有两个原始指针,并且第一次调用new
成功,但第二次失败,析构函数将不会运行,第一个指针永远不会是{{1} } d。但是如果你的对象有两个智能指针,第一个被成功构建而第二个失败了,第一个智能指针会被正确销毁,你不必担心它。