我写了这段代码 构造函数正常工作,但在析构函数中,我得到“Windows触发了一个断点”。我该怎么纠正这个?
template class CyclicalArray {
private:
T* mem_ptr;
public:
CyclicalArray(size_t capacity, const T& default_value) {
this->default_value = default_value;
this->capacity = capacity;
head_index = 0;
mem_ptr = ::new T[capacity]; //memory allocating
for(T* p = mem_ptr; p < mem_ptr + capacity * sizeof(T); p += sizeof(T)) {
::new (p) T (default_value); //initialization
}
}
~CyclicalArray() {
for(T* p = mem_ptr + sizeof(T); p < mem_ptr + capacity * sizeof(T); p += sizeof(T)) {
p->~T();
}
delete[] mem_ptr;
}
答案 0 :(得分:8)
如果您要执行新的放置,则需要在原始内存上执行此操作。类似的东西:
template class CyclicalArray {
private:
T* mem_ptr;
public:
CyclicalArray(size_t capacity, const T& default_value) {
this->default_value = default_value;
this->capacity = capacity;
head_index = 0;
mem_ptr = reinterpret_cast<T*>( ::new char[capacity * sizeof(T)]); //memory allocating
for(T* p = mem_ptr; p < mem_ptr + capacity; ++p) {
::new (p) T (default_value); //initialization
}
}
~CyclicalArray() {
// this
for(T* p = mem_ptr + capacity; p != mem_ptr; --p) {
(p-1)->~T();
}
delete[] reinterpret_cast<char*>( mem_ptr);
}
否则你将在相同的对象内存上调用两次T析构函数(这不是一件好事)。
此外,由于您的p
指针属于T*
类型,您可以对其执行简单的递增/递减 - 编译器将处理sizeof(T)
问题作为指针的正常过程算术。
最后,严格来说,你应该按降序销毁数组元素(与构造相反)。
我希望能够捕获大部分或全部错误。
您可能真的想考虑使用std :: vector之类的东西作为商店。下面是使用std::vector<>
的示例(还有一些其他语法修复)。我不确定你的班级是否真的需要default_value
或head_index
的副本 - 我让他们假设你打算在其他方法中使用它们:
#include <vector>
template <typename T>
class CyclicalArray {
private:
std::vector<T> backing_store;
T default_value;
size_t head_index;
public:
CyclicalArray(size_t capacity, const T& def_val) :
backing_store(capacity, def_val),
default_value( def_val),
head_index(0) {
}
~CyclicalArray() {}
};
注意构造函数和析构函数有多简单,因为第一个类的所有复杂性都由std:vector
管理。
答案 1 :(得分:7)
你可能会超越mem_ptr
数组的末尾。在C和C ++中,指针算法以所涉及的类型为单位,而不是字节。例如,如果您有int *a;
,那么如果a
为0x100,sizeof(int) == 4
,则a + 1
为0x104。
因此,您将p
增加平方类型的大小,因为向其添加1会将其移动sizeof(T)
个字节,因此向其添加sizeof(T)
会增加它太多了。
更不用说您不需要在数组中调用单个析构函数,因为delete []
会为您处理。
答案 2 :(得分:1)
使用全局函数operator new
代替运算符new
。它将分配内存但不会调用构造函数。删除相同:
template class CyclicalArray {
private:
T* mem_ptr;
public:
CyclicalArray(size_t capacity, const T& default_value) {
this->default_value = default_value;
this->capacity = capacity;
head_index = 0;
mem_ptr = static_cast<T*>(::operator new[] (sizeof(T)*capacity)); //memory allocating
for(T* p = mem_ptr; p < mem_ptr + capacity; p ++ ) {
::new (p) T (default_value); //initialization
}
}
~CyclicalArray() {
for(T* p = mem_ptr; p < mem_ptr + capacity; p ++) {
p->~T();
}
::operator delete[]( static_cast<void*>(mem_ptr) );
}
答案 3 :(得分:1)
您正在调用构造函数和析构函数两次,因为您使用的是new-expression和delete-expression:
// This allocates and calls constructor
mem_ptr = ::new T[size];
// This calls the destructor and deallocates the memory
delete[] mem_ptr;
如果您只想分配原始内存,可以显式调用operator new:
// This simply allocates raw memory
mem_ptr = ::operator new(sizeof(T) * size);
// And this simply deallocates memory
::operator delete(mem_ptr);
答案 4 :(得分:1)
为什么要使用新的放置?该代码基本归结为:
template <class T>
class CyclicalArray {
private:
T* mem_ptr;
size_t capacity;
T default_value;
size_t head_index;
public:
CyclicalArray(size_t capacity, const T& default_value) : capacity(capacity), default_value(default_value), head_index(0) {
mem_ptr = new T[capacity](default_value); //memory allocating and construction
}
~CyclicalArray() {
delete[] mem_ptr;
}
};
编辑:如果您确实想要使用展示位置新功能,那么您的循环应如下所示:
for(T* p = mem_ptr; p != mem_ptr + capacity; ++p) {
无需按sizeof(T)
缩放,这是在C / C ++中为您完成的。