auto_ptr 包含 POD 和未初始化值的数组
auto_ptr with an array of POD and uninitialized values
这与 auto_ptr for arrays 非常相似。然而,我的皱纹是我不想要一个初始化数组,这是 vector
会提供的(const T& value = T()
):
explicit vector(size_type count,
const T& value = T(),
const Allocator& alloc = Allocator());
我不想初始化数组,因为它是一个大数组,值将被立即丢弃。
我目前正在用以下方法破解它,但感觉它有问题:
//! deletes an array on the heap.
template <class T>
class AutoCleanup
{
public:
AutoCleanup(T*& ptr) : m_ptr(ptr) { }
~AutoCleanup() { if (m_ptr) { delete[] m_ptr; m_ptr = NULL; }}
private:
T*& m_ptr;
};
并且:
// AutoCleanup due to Enterprise Analysis finding on the stack based array.
byte* plaintext = new byte[20480];
AutoCleanup<byte> cleanup(plaintext);
// Do something that could throw...
对于未初始化和正确删除的 POD 类型的数组,C++ 提供了什么?
项目是C++03,没有像Boost那样的外部依赖。
从你的问题来看,要解释你真正需要什么并不容易。但我猜你想要一个堆栈保护(即生命周期绑定到堆栈)、堆分配、未初始化、动态或静态大小并且与 C++11 之前的编译器兼容的数组。
auto_ptr
无法处理数组(因为它不在其析构函数中调用 delete[]
,而是 delete
)。
相反,我会将 boost::scoped_array
与 new[]
一起使用(据我所知,它不会初始化 POD 类型)。
boost::scoped_array<MyPodType> a(new MyPodType[20480]);
如果您不想使用 boost,您可以通过将此 class 从 boost 库中包含的代码粘贴在一起来非常轻松地重新实现 scoped_array
:
#include <cassert>
#include <cstddef>
// From <boost/checked_delete.hpp>:
template<class T>
inline void checked_array_delete(T * x)
{
typedef char type_must_be_complete[sizeof(T) ? 1 : -1];
(void) sizeof(type_must_be_complete);
delete [] x;
}
// From <boost/smartptr/scoped_array.hpp>:
template<class T>
class scoped_array
{
private:
T * px;
// Make this smart pointer non-copyable
scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &);
typedef scoped_array<T> this_type;
public:
typedef T element_type;
explicit scoped_array(T * p = 0) : px(p) { }
~scoped_array() {
checked_array_delete(px);
}
void reset(T * p = 0) {
assert(p == 0 || p != px); // catch self-reset errors
this_type(p).swap(*this);
}
T & operator[](std::ptrdiff_t i) const {
assert(px != 0);
assert(i >= 0);
return px[i];
}
T * get() const {
return px;
}
operator bool () const {
return px != 0;
}
bool operator ! () const {
return px == 0;
}
void swap(scoped_array & b) {
T * tmp = b.px;
b.px = px;
px = tmp;
}
};
这与 auto_ptr for arrays 非常相似。然而,我的皱纹是我不想要一个初始化数组,这是 vector
会提供的(const T& value = T()
):
explicit vector(size_type count,
const T& value = T(),
const Allocator& alloc = Allocator());
我不想初始化数组,因为它是一个大数组,值将被立即丢弃。
我目前正在用以下方法破解它,但感觉它有问题:
//! deletes an array on the heap.
template <class T>
class AutoCleanup
{
public:
AutoCleanup(T*& ptr) : m_ptr(ptr) { }
~AutoCleanup() { if (m_ptr) { delete[] m_ptr; m_ptr = NULL; }}
private:
T*& m_ptr;
};
并且:
// AutoCleanup due to Enterprise Analysis finding on the stack based array.
byte* plaintext = new byte[20480];
AutoCleanup<byte> cleanup(plaintext);
// Do something that could throw...
对于未初始化和正确删除的 POD 类型的数组,C++ 提供了什么?
项目是C++03,没有像Boost那样的外部依赖。
从你的问题来看,要解释你真正需要什么并不容易。但我猜你想要一个堆栈保护(即生命周期绑定到堆栈)、堆分配、未初始化、动态或静态大小并且与 C++11 之前的编译器兼容的数组。
auto_ptr
无法处理数组(因为它不在其析构函数中调用 delete[]
,而是 delete
)。
相反,我会将 boost::scoped_array
与 new[]
一起使用(据我所知,它不会初始化 POD 类型)。
boost::scoped_array<MyPodType> a(new MyPodType[20480]);
如果您不想使用 boost,您可以通过将此 class 从 boost 库中包含的代码粘贴在一起来非常轻松地重新实现 scoped_array
:
#include <cassert>
#include <cstddef>
// From <boost/checked_delete.hpp>:
template<class T>
inline void checked_array_delete(T * x)
{
typedef char type_must_be_complete[sizeof(T) ? 1 : -1];
(void) sizeof(type_must_be_complete);
delete [] x;
}
// From <boost/smartptr/scoped_array.hpp>:
template<class T>
class scoped_array
{
private:
T * px;
// Make this smart pointer non-copyable
scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &);
typedef scoped_array<T> this_type;
public:
typedef T element_type;
explicit scoped_array(T * p = 0) : px(p) { }
~scoped_array() {
checked_array_delete(px);
}
void reset(T * p = 0) {
assert(p == 0 || p != px); // catch self-reset errors
this_type(p).swap(*this);
}
T & operator[](std::ptrdiff_t i) const {
assert(px != 0);
assert(i >= 0);
return px[i];
}
T * get() const {
return px;
}
operator bool () const {
return px != 0;
}
bool operator ! () const {
return px == 0;
}
void swap(scoped_array & b) {
T * tmp = b.px;
b.px = px;
px = tmp;
}
};