C++ 为什么删除字符时会出现内存异常*

C++ 为什么删除字符时会出现内存异常*,c++,string,algorithm,memory,memory-management,C++,String,Algorithm,Memory,Memory Management,我正在尝试编写自己的字符串类(以便了解更多信息),在编写过程中,我注意到遇到了一个问题,即如何删除char数据,当程序关闭时,将调用string的析构函数,删除数据时将出现堆错误 #include <string.h> template<typename T> class String { protected: T* mData; public: String(const T* data); ~String(); }; template<

我正在尝试编写自己的字符串类(以便了解更多信息),在编写过程中,我注意到遇到了一个问题,即如何删除char数据,当程序关闭时,将调用string的析构函数,删除数据时将出现堆错误

#include <string.h>

template<typename T>
class String
{
protected:
    T* mData;

public:
    String(const T* data);
    ~String();
};

template<typename T>
String<T>::String(const T* data)
{
    if(data != NULL)
    {
        mData = new T[strlen(data)];
        strcpy(mData, data);
    }
}

template<typename T>
String<T>::~String()
{
    if(mData != NULL)
    {
        delete [] mData;
        mData = 0;
    }
}

int main(void)
{
    String<char> Test("Test");

    return(0);
}
#包括
模板
类字符串
{
受保护的:
T*mData;
公众:
字符串(常数*数据);
~String();
};
模板
字符串::字符串(常量T*数据)
{
如果(数据!=NULL)
{
mData=新的T[strlen(数据)];
strcpy(mData,data);
}
}
模板
字符串::~String()
{
如果(mData!=NULL)
{
删除[]mData;
mData=0;
}
}
内部主(空)
{
字符串测试(“测试”);
返回(0);
}
如果分配的项目太少,strcpy会复制nul终止字节和字符串

您应该使用“memcpy”和“memset”函数,而不是像strcpy那样的函数:


对于在构造函数中引发异常的新运算符,您必须小心。如果发生这种情况,您必须确保已初始化指向nullptr、otherwize的数据指针,将调用析构函数并尝试删除一些随机地址

#include <cstring>

template<typename T>
class string {
    protected:
        T * data_;
    public:
        string(T const * data);
        ~string();
};

template<typename T>
string<T>::string(T const * data)
try {
    if(!data) data_ = 0;
    else {
        data_ = new T[std::strlen(data) + 1];
        std::strcpy(data_, data);
    }
} catch(...) {
    data_ = 0;
}

template<typename T>
string<T>::~string() {
    delete[] data_;
}

int main() {
    string<char> test("test");
    return 0;
}
#包括
模板
类字符串{
受保护的:
T*数据;
公众:
字符串(T常量*数据);
~string();
};
模板
字符串::字符串(T常量*数据)
试一试{
如果(!data)data_u0;
否则{
数据=新T[std::strlen(数据)+1];
标准::strcpy(数据,数据);
}
}捕获(…){
数据=0;
}
模板
字符串::~string(){
删除[]数据;
}
int main(){
字符串测试(“测试”);
返回0;
}

删除前无需测试NULL(或将值设置为0 afterwords)。您需要遵守三个规则。你是对的,我违反了三条规则(我想要一个简单的测试用例),就是这样,我完全忘记了这一点。感谢您的帮助。通过使用“memcpy”函数,您可以使用快速的内存块。另外,“strcpy”是不安全的,因为它可能导致溢出。在您的情况下,有一个“strlcpy”函数是安全的。当您使用内存块功能时,您可以完全控制内存。就我个人而言,我更喜欢两个字符串类别,一个用于char类型,另一个用于wchar\t类型,两者都继承自同一个泛型抽象类(接口),而不是使用模板(泛型)。
#include <cstring>

template<typename T>
class string {
    protected:
        T * data_;
    public:
        string(T const * data);
        ~string();
};

template<typename T>
string<T>::string(T const * data)
try {
    if(!data) data_ = 0;
    else {
        data_ = new T[std::strlen(data) + 1];
        std::strcpy(data_, data);
    }
} catch(...) {
    data_ = 0;
}

template<typename T>
string<T>::~string() {
    delete[] data_;
}

int main() {
    string<char> test("test");
    return 0;
}