gpt4 book ai didi

c++ - 删除指针成员数组,然后重新分配它

转载 作者:行者123 更新时间:2023-11-30 03:41:01 28 4
gpt4 key购买 nike

我正在创建一个堆栈类作为尝试学习一些 C++ 概念(此处为初始化程序列表、内存管理和模板)的练习。我遇到了一些我无法理解的事情。

在函数 void Stack::push(const T& item) 中,如果我取消注释 delete [] 数据;行,当模板参数是例如 int 或 char 时,我的代码运行良好。但是对于 std::string,我会遇到奇怪的内存错误。

我的想法是,我需要一个更大的数组 -> 数组不能调整大小 -> 我创建一个新数组 -> 我为即将不需要的数组释放我需要的内存 -> 我做了existing 指针指向一个新的内存地址,我在其中创建了更大的数组。

现在,当我注释删除行时,代码即使使用 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 objects 的内容会被复制,但这基本上只是指针和大小。当您执行按位复制时,您将有两个引用同一内存的 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++ - 删除指针成员数组,然后重新分配它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37613035/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com