我的字符串类有问题。在cin.get
编译器显示此表达式后。我哪里出错了?
//Source.cpp
#include <iostream>
#include <string>
#include "str.h"
using namespace std;
int main()
{
str S1 = "Hello, world!";
str S2 = "LOL";
str S3 = S2;
cout << S3.cstr() << endl;
cout << S1.size() << ": " << S1.cstr() << endl;
cin.get();
}
//str.h
#ifndef STR_H
#define STR_H
class str
{
public:
str(const char* = "");
~str();
void operator=(const char*);
void operator=(str);
const char* cstr();
int size();
private:
void newString(const char*);
char* charPtr;
int Size;
};
#endif
//str.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <cstring>
using std::strlen;
using std::strcpy;
#include "str.h"
str::str(const char* cstr)
{
newString(cstr);
}
str::~str()
{
delete[] charPtr;
}
const char* str::cstr()
{
return charPtr;
}
void str::newString(const char* cstr)
{
delete[] charPtr;
Size = strlen(cstr);
charPtr = new char[Size + 1];
strcpy(charPtr, cstr);
}
void str::operator=(const char* cstr)
{
newString(cstr);
}
int str::size()
{
return Size;
}
答案 0 :(得分:1)
你没有服从rule of three。您有用户定义的析构函数和复制赋值运算符,但您尚未定义复制构造函数。编译器帮助</sarcasm>
为您定义了一个。
在这一行:
str S3 = S2;
你copy initialize S3。正如您可以从链接页面中的规则中看到的那样:
如果T是类类型而其他类型是cv非限定版本的T或从T派生的类,则检查T的构造函数,并通过重载决策选择最佳匹配。然后调用构造函数来初始化对象。
最佳匹配构造函数恰好是编译器添加的str(const str&);
。默认的复制构造函数不会复制charPtr指向的数据,而只是复制指针。
当S2超出范围时,在cin.get();
之后,它的析构函数删除了S2.charPtr。接下来,S3被销毁,它的析构函数尝试删除S3.charPtr,它具有与S2.charPtr相同的值,因此已被删除。 This has undefined behaviour。 Quick googling表示如果堆指针无效,则_BLOCK_TYPE_IS_VALID
断言失败。我猜这可能是这种未定义行为的结果。
解决方案:实施复制构造函数str(const str&);
,以便副本不共享数据。