删除指针的成员数组,然后重新分配它
Deleting a member array of pointers, then reallocating it
我正在创建一个堆栈类作为练习,试图学习一些 c++ 概念(此处为初始值设定项列表、内存管理和模板)。我遇到了一些我无法理解的事情。
在函数void Stack::p ush(const T&item)中,如果我取消注释删除[]数据;行,当模板参数是例如int或char时,我的代码运行良好。但是使用 std::string,我得到了奇怪的内存错误。
我在这里的想法是,我需要更大的数组 ->数组无法调整大小 ->我创建一个新的数组 ->我为很快不需要的数组释放所需的内存 -> 我使现有指针指向一个新的内存地址,我在其中创建更大的数组。
现在,当我注释删除行时,即使使用 std::string,代码也能运行良好,但我不明白为什么我不能安全地对所有类型进行删除操作。
任何见解将不胜感激。
#include <iostream>
#include <stdio.h>
#include <memory.h>
template<class T>
class Stack
{
T* data;
int sz;
public:
//Stack(){sz=0;}
Stack(const std::initializer_list<T>&);
~Stack();
void push(const T&);
T& pop();
void show() const;
};
template<class T>
Stack<T>::Stack(const std::initializer_list<T> &list)
{
sz=0;
data = new T[list.size()];
for (auto i : list) {
data[sz] = i;
++sz;
}
std::cout<< "Created with sz: "<< sz<<std::endl;
}
template<class T>
Stack<T>::~Stack()
{
delete [] data;
}
template<class T>
void Stack<T>::push(const T& item) {
std::cout<<"push "<<item<<std::endl;
T* arr = new T[sz];
memcpy(arr, data, sz*sizeof(T));
//delete [] data;
data = new T[sz + 1];
memcpy(data, arr, sz*sizeof(T));
++sz;
data[sz - 1] = item;
std::cout<<"new size: "<<sz<<", bytes: "<<sz*sizeof(T)<<std::endl;
}
template<class T>
T& Stack<T>::pop()
{
if(sz > 0) {
std::cout<<"pop "<<data[sz-1]<<std::endl;
std::cout<<"new size: "<<sz-1<<std::endl;
return data[--sz];
}
else
return data[0];
}
template<class T>
void Stack<T>::show() const
{
for (int i=0; i<sz; i++) {
std::cout<<data[i]<<" ";
}
std::cout<<std::endl;
}
int main(){
Stack<int> s = {1,2,3,4,5,6,7,8,9,10,11};
s.show();
s.push(12);
s.push(13);
s.push(14);
s.pop();
s.pop();
s.push(15);
s.push(16);
s.show();
Stack<std::string> d = {"one","two","three"};
d.show();
d.pop();
d.push("four");
d.show();
return 0;
}
不要使用
memcpy
来复制对象,这将正确复制位,但对于某些对象,按位复制不正确,因为不会使用复制构造函数(或复制赋值运算符)。
一个很好且简单的例子是,如果您有一堆std::string
对象。当您执行按位复制(使用 memcpy
)时,将复制std::string
对象的内容,但这基本上只是一个指针和一个大小。执行按位复制时,将有两个std::string
对象引用同一内存。销毁其中一个对象将导致另一个对象具有指向某个内存(用于包含字符串)的杂散指针,该内存不再由程序拥有。
要解决此问题,请使用std::copy
而不是复制对象,它将做正确的事情。
与您的问题无关,但您的 push
函数会执行它不需要的副本:
T* arr = new T[sz];
memcpy(arr, data, sz*sizeof(T));
这根本不需要,而是做类似的事情
T* oldData = data;
data = new T[sz + 1];
// Copy from old array to new
std::copy(oldData, oldData + sz, data);
delete[] oldData;
相关文章:
- C++ 如何在将新对象分配给另一个对象时创建新对象
- 如何增加以前由新运算符分配的 C++ std::list 数组的大小?
- 为模板参数类型中的新对象分配内存
- 新运算符分配的大小大于声明的大小.为什么
- 在C++中分配分配
- 为什么支撑初始化分配分配填充垃圾变量
- C 新操作员分配新内存
- 新不分配内存?
- 如果我的C++“新”内存分配失败,如何找出返回值
- 我可以用新的分配内存块吗?
- COM / DCOM:服务器存根不会为现有接口中的新方法分配内存
- 在线程在 C++ 中完成后将新任务分配给线程
- 只能使用CUDA中的新运算符分配有限的内存
- 与将新内容分配给向量的指针斗争
- 确定C++中新运算符分配的内存大小
- 按新内存分配
- 是否有必要使用 'new' 将新指针分配给与指向同一结构的先前存在的指针相同的结构?如果是这样,为什么?
- 用于新运算符分配的公共内存
- boost::io_service post方法是否引起新的分配?
- 如何在C++中检索由新运算符分配的对象的地址