我编译了我的代码,但它告诉我“抛出异常:读取访问冲突。 _First是nullptr。“
我完全不知道这意味着什么,因为我还是C ++的初学者。我真的需要你的帮助才能解决这个问题,因为我几天来一直在努力解决这个问题,这太令人沮丧......
提前谢谢你。
#include <iostream>
#include <cstring>
#include <fstream>
using namespace std;
class MyString {
public:
//default constructor
MyString();
MyString(char* chars);
//copy constructor
MyString(const MyString &);
int length() const;
//destructor
~MyString();
//operator overloads
char& operator[](int index);
friend MyString operator+(const MyString& newWord, const MyString& newWord2);
MyString& operator+=(const MyString& newWord);
friend ostream& operator<<(ostream& newWord, const MyString& newWord2);
friend istream& operator >> (istream& newWord, MyString& newWord2);
friend bool operator==(const MyString& newWord, const MyString& newWord2);
friend bool operator!=(const MyString& newWord, const MyString& newWord2);
friend bool operator<(const MyString& newWord, const MyString& newWord2);
friend bool operator<=(const MyString& newWord, const MyString& newWord2);
friend bool operator>(const MyString& newWord, const MyString& newWord2);
friend bool operator>=(const MyString& newWord, const MyString& newWord2);
private:
char* value;
int size;
};
//default constructor
MyString::MyString() {
value = NULL;
size = 0;
}
//copy constructor
MyString::MyString(const MyString& newWord) {
//perform a deep copy to copy each of the value to a new memory
size = newWord.size;
char* newCopy = new char[size];
for (int ii = 0; ii < size; ii++) {
newCopy[ii] = newWord.value[ii];
}
}
//constructor with an argument
MyString::MyString(char* chars) {
//give the value and the size
value = chars;
size = strlen(chars);
}
//find length
int MyString::length() const {
return size;
}
//find the value of each index
char& MyString::operator[](int index) {
return value[index];
}
//operator + (concatenate)
MyString operator+(const MyString& newWord, const MyString& newWord2) {
MyString concatenated;
concatenated = strcat(newWord.value, newWord.value);
return concatenated;
}
//operator += (append)
MyString& MyString::operator+=(const MyString& newWord) {
char * newMemory = value;
value = new char[strlen(value) + newWord.length() + 1];
strcpy(value, newMemory);
strcat(value, newWord.value);
if (size != 0)
{
delete[] newMemory;
}
size = strlen(value);
return *this;
}
//ostream operator
ostream& operator<<(ostream& newWord, const MyString& newWord2) {
newWord << newWord2.value;
return newWord;
}
//istream operator
istream& operator >> (istream& newWord, MyString& newWord2) {
const int MAX = 100;
char* ptr = new char[MAX];
newWord >> ptr;
newWord2 = MyString(ptr);
delete ptr;
return newWord;
}
//all boolean operators
bool operator==(const MyString& newWord, const MyString& newWord2) {
if (newWord.value == newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator!=(const MyString& newWord, const MyString& newWord2) {
if (newWord.value != newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator<(const MyString& newWord, const MyString& newWord2) {
if (newWord.value < newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator<=(const MyString& newWord, const MyString& newWord2) {
if (newWord.value <= newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator>(const MyString& newWord, const MyString& newWord2) {
if (newWord.value > newWord2.value) {
return true;
}
else {
return false;
}
}
bool operator>=(const MyString& newWord, const MyString& newWord2) {
if (newWord.value >= newWord2.value) {
return true;
}
else {
return false;
}
}
//destructor to release memory
MyString::~MyString() {
delete[] value;
}
void test_copy_and_destructor(MyString S) {
cout << "test: copy constructor and destructor calls: " << endl;
MyString temp = S;
cout << "temp inside function test_copy_and_destructor: " << temp << endl;
}
int main() {
MyString st1("abc abc");
MyString st2("9fgth");
cout << "Copy constructor , << operator" << endl;
MyString st3(st1);
cout << "st3: " << st3 << endl;
test_copy_and_destructor(st2);
MyString st4;
cout << "operator + " << endl;
st4 = st3 + st2;
cout << "st4: " << st4 << endl;
cout << "st1 + st2: " << (st1 + st2) << endl;
cout << "operators [ ] " << endl;
for (int i = 0; i < st2.length(); i++)
cout << st2[i] << " ";
cout << endl;
cout << "operators += , ==, != " << endl;
st2 += st1;
if (st3 == st1)
cout << "st3 and st1 are identical " << endl;
else cout << "st3 and st1 are not identical " << endl;
if (st2 != st1)
cout << "st2 and st1 are not identical " << endl;
else cout << "st2 and st1 are identical " << endl;
cout << "operators < , <=, >, >= " << endl;
if (st2 < st1)
cout << "st2 < st1 " << endl;
else cout << "st2 is not less than st1 " << endl;
if (st1 <= st2)
cout << "st1 <= st2 " << endl;
else cout << "st1 is not less than or equal to st2 " << endl;
if (st1 > st2)
cout << "st1 > st2 " << endl;
else cout << "not (st1 > st2) " << endl;
if (st1 >= st2)
cout << "st1 >= st2 " << endl;
else cout << "not (st1 >= st2) " << endl;
cout << "operator >> " << endl;
//Open the data file
ifstream input("A9_input.txt");
if (input.fail()) {
cout << "unable to open input file A9_input.txt, Exiting..... ";
system("pause");
return 0;
}
MyString temp1;
MyString temp2("aaa");
input >> temp1;
input >> temp2;
cout << "first element of input file: " << temp1 << endl;
cout << "second element of input file: " << temp2 << endl;
input.close();
cout << "MyString says farewell....." << endl;
system("pause");
return 0;
}
答案 0 :(得分:1)
您的复制构造函数从不设置目标的value
,因此当您尝试使用新字符串时,value
未初始化。您应该分配给newCopy
。
value
MyString::MyString(const MyString& newWord) {
//perform a deep copy to copy each of the value to a new memory
size = newWord.size;
value = new char[size];
for (int ii = 0; ii < size; ii++) {
value[ii] = newWord.value[ii];
}
}
此外,使用char* chars
的构造函数必须复制chars
。否则,如果参数是超出范围的本地数组或已删除的动态数组,则指针可能变为无效。此外,由于析构函数执行delete[] value;
,因此需要动态分配,这在从字符串文字初始化时不正确。
//constructor with an argument
MyString::MyString(char* chars) {
size = strlen(chars);
value = new char[size];
for (int i = 0; i < size; i++) {
value[i] = chars[i];
}
}
答案 1 :(得分:0)
有一系列问题需要解决:
首先,允许value
为0 / NULL / nullptr(最好使用新的c ++ 11 nullptr关键字!)。如果这样做,您需要在每个函数和运算符中考虑这种可能性,否则您将尝试访问无效的内存位置(例如,在执行strlen(value)
时)。这正是异常的意思(0在大多数情况下没有有效的内存地址,嵌入式系统存在一些例外 - 但是,如果写入它,你可能会破坏整个系统!):你遇到了这种情况。 / p>
为了避免每个函数/运算符中的麻烦,您可能更喜欢始终将value
设置为构造函数中的现有空字符串isady,就像std :: string一样(异常:不是每个std的实现: :string确实接受std::string(nullptr)
)。您也可以为用户避免另一个问题:您启用了他为大小为0的字符串获取两个不同的字符串表示形式:nullptr
和""
。
另一个问题是,如果构造函数接受char*
,则不复制字符串,但在析构函数中删除它。问题:参数可以是在堆栈上分配的char缓冲区:
char buffer[64];
/* ... */
return MyString(buffer);
在许多情况下获取现有字符串的所有者可能是有效的(使用std :: string是不可能的 - 在每种情况下都是安全的,在某些中效率低下),但是你可能会遇到深层问题在其他人中(如上所述,或者如果指定字符串文字return MyString("hello world");
(好吧,无论如何这都是有问题的,因为文字在C ++中是char const*
- 但是许多编译器让你逃脱它,只是提出警告如果你想允许取得所有权,我默认情况下不会这样做(复制字符串),并明确地添加另一个构造函数(MyString(char*, bool takeOwnership = false)
,同时(MyString(char const*)
总是复制 - 注意const
)。当然,如果你有所有权,你需要记住某个地方。如果你有所有权(默认......),只删除内部表示。
您正在通过==,!=,&lt;,&gt;,...运算符比较char*
值。请注意,只有当两个value
成员指向完全相同的字符串时才会获得相等,但是如果两个不同的字符串在字面上相等则不会:
char b1[] = {'a', 'b', 'c', 0 };
char b2[] = {'a', 'b', 'c', 0 };
bool isEqual = MyString(b1) == MyString(b2);
isEqual
将是false
!我假设您不打算这样做,而是与std :: string提供的行为相同。更严重的问题是运算符&lt;,&lt; =,&gt;,&gt; =。仅当两个指针指向同一个数组或者指向一个结尾(b3 = b1 + 2
)时才与它们进行比较是合法的,否则,它是未定义的行为。
要获得我想要的行为,您需要使用strcmp
:
bool operator X(MyString const& l, MyString const& r)
{
return strcmp(l, r) X 0;
}
使用适当的运算符替换X的位置(请注意,您可以将!=
定义为!(l == r)
,<=
定义为!(l > r)
等。
请拜托,请:不要做这样的事情:
if(a == b)
return true;
else
return false;
或
bool isWhatEver;
if(c != d)
isWhatEver = true;
else
isWhatEver = false;
简单写一下
return a == b;
isWhatEver = c != d;
<强>附录:强>
您违反rule of three,未提供作业运算符:operator=(MyString const& other)
。三个规则实际上变成了rule of five与C ++ 11;您可能还想添加移动构造函数和移动赋值运算符。在实施之前,请查看here,这可能对您非常有用......
修改强>
几乎不可能只从地址说出来,出了什么问题。你没有提供任何堆栈跟踪而不是你的固定代码...
所以我允许自己修改你认为你可能有意的课程。这个版本贯穿了你所有的测试,至少,输入文件的内容只是'hello world'。省略移动构造函数(提示:为此使用std :: swap)。我仍然不保证它是无错误的...有些建议:不要只是接受我的代码,仔细看看我做了什么不同,看看可能出了什么问题。最后一件事:我做了运营商&gt;&gt;因使用std :: vector超出缓冲区大小而安全地防止失败。
class MyString
{
public:
//default constructor
MyString();
MyString(char const* chars);
//copy constructor
MyString(const MyString &);
int length() const;
//destructor
~MyString();
//operator overloads
char& operator[](int index);
friend MyString operator+(const MyString& newWord, const MyString& newWord2);
MyString& operator+=(const MyString& newWord);
MyString& operator=(const MyString& newWord)
{
char* newValue = new char[newWord.size];
delete value;
value = newValue;
size = newWord.size;
memcpy(value, newWord.value, size);
return *this;
}
MyString& operator=(char const* chars)
{
size_t newSize = strlen(chars);
char* newValue = new char[newSize];
delete value;
value = newValue;
size = newSize;
memcpy(value, chars, size);
return *this;
}
friend ostream& operator<<(ostream& newWord, const MyString& newWord2);
friend istream& operator >>(istream& newWord, MyString& newWord2);
friend bool operator==(const MyString& newWord, const MyString& newWord2);
friend bool operator!=(const MyString& newWord, const MyString& newWord2);
friend bool operator<(const MyString& newWord, const MyString& newWord2);
friend bool operator<=(const MyString& newWord, const MyString& newWord2);
friend bool operator>(const MyString& newWord, const MyString& newWord2);
friend bool operator>=(const MyString& newWord, const MyString& newWord2);
private:
char* value;
int size;
};
//default constructor
MyString::MyString()
{
value = new char[1];
*value = 0;
size = 0;
}
//copy constructor
MyString::MyString(const MyString& newWord)
{
//perform a deep copy to copy each of the value to a new memory
size = newWord.size;
value = new char[size];
memcpy(value, newWord.value, size);
}
//constructor with an argument
MyString::MyString(char const* chars)
{
if(chars)
{
size = strlen(chars);
value = new char[size];
memcpy(value, chars, size);
}
else
{
value = new char[1];
*value = 0;
size = 0;
}
}
//find length
int MyString::length() const
{
return size;
}
//find the value of each index
char& MyString::operator[](int index)
{
return value[index];
}
//operator + (concatenate)
MyString operator+(const MyString& newWord, const MyString& newWord2)
{
MyString concatenated;
concatenated.value = new char[newWord.size + newWord2.size + 1];
memcpy(concatenated.value, newWord.value, newWord.size);
memcpy(concatenated.value + newWord.size, newWord2.value, newWord2.size + 1);
return concatenated;
}
//operator += (append)
MyString& MyString::operator+=(const MyString& newWord)
{
if(newWord.size > 0)
{
char * newMemory = value;
value = new char[size + newWord.size + 1];
memcpy(value, newMemory, size);
memcpy(value + size, newWord.value, newWord.size);
delete[] newMemory;
size += newWord.size;
}
return *this;
}
//ostream operator
ostream& operator<<(ostream& newWord, const MyString& newWord2)
{
newWord << newWord2.value;
return newWord;
}
//istream operator
istream& operator >>(istream& newWord, MyString& newWord2)
{
std::vector<char> v;
for(;;)
{
char c = newWord.get();
if(newWord.eof() || isspace(c))
{
break;
}
v.push_back(c);
}
if(!v.empty())
{
newWord2 = v.data();
}
return newWord;
}
//all boolean operators
bool operator==(const MyString& newWord, const MyString& newWord2)
{
return strcmp(newWord.value, newWord2.value) == 0;
}
bool operator!=(const MyString& newWord, const MyString& newWord2)
{
return !(newWord == newWord2);
}
bool operator<(const MyString& newWord, const MyString& newWord2)
{
return strcmp(newWord.value, newWord2.value) < 0;
}
bool operator>(const MyString& newWord, const MyString& newWord2)
{
return strcmp(newWord.value, newWord2.value) < 0;
}
bool operator<=(const MyString& newWord, const MyString& newWord2)
{
return !(newWord > newWord2);
}
bool operator>=(const MyString& newWord, const MyString& newWord2)
{
return !(newWord < newWord2);
}
//destructor to release memory
MyString::~MyString()
{
delete[] value;
}