嘿所有,我正在构建具有非常基本功能的自己的字符串类。我很难理解我所定义的基本类正在发生什么,并且相信在处理范围时会出现某种错误。当我尝试查看我创建的对象时,所有字段都被描述为(显然是错误的指针)。此外,如果我公开数据字段或构建一个访问器方法,程序崩溃。由于某种原因,对象的指针是0xccccccccc,它指向no where 我怎么能解决这个问题?非常感谢任何帮助/评论。
//This is a custom string class, so far the only functions are
//constructing and appending
#include<iostream>
using namespace std;
class MyString1
{
public:
MyString1()
{
//no arg constructor
char *string;
string = new char[0];
string[0] ='\0';
std::cout << string;
size = 1;
}
//constructor receives pointer to character array
MyString1(char* chars)
{
int index = 0;
//Determine the length of the array
while (chars[index] != NULL)
index++;
//Allocate dynamic memory on the heap
char *string;
string = new char[index+1];
//Copy the contents of the array pointed by chars into string, the char array of the object
for (int ii = 0; ii < index; ii++)
string[ii] = chars[ii];
string[index+1] = '\0';
size = index+1;
}
MyString1 append(MyString1 s)
{
//determine new size of the appended array and allocate memory
int newsize = s.size + size;
MyString1 MyString2;
char *newstring;
newstring = new char[newsize+1];
int index = 0;
//load the first string into the array
for (int ii = 0; ii < size; ii++)
{
newstring[ii] = string[ii];
index++;
}
for(int jj = 0; jj < s.size; jj++, ii++)
{
newstring[ii] = s.string[jj++];
index++;
}
//null terminate
newstring[newsize+1] = '\0';
delete string;
//generate the object for return
MyString2.string=newstring;
MyString2.size=newsize;
return MyString2;
}
private:
char *string;
int size;
};
int main()
{
MyString1 string1;
MyString1 string2("Hello There");
MyString1 string3("Buddy");
string2.append(string3);
return 0;
}
编辑: 到目前为止,感谢大家回应并处理我对此主题缺乏了解的问题。我将开始处理所有的答案,但再次感谢您的回复,对不起,我的问题很模糊,但实际上没有特定的错误,但更多的是缺乏对数组和类的理解。
答案 0 :(得分:3)
这只是第一个构造函数的错误。
MyString1()
{
//no arg constructor
char *string; //defines local variable that hides the member by that name
string = new char[0]; //sort of meaningless
string[0] ='\0'; //not enough room for that (out-of-bounds)
std::cout << string;
size = 1; //I don't think you should count null as part of the string
}
其他地方也有类似的错误。
此外,您应该更仔细地传递参数。
MyString1(const char* source); //note const
MyString1 append(const MyString1& what); //note const and reference
如果后者是正确的,还取决于它应该做什么。基于std::string
,预期结果将是:
MyString1 a("Hello "), b("world");
a.append(b);
assert(a == "Hello world");
答案 1 :(得分:2)
对您的代码的一些评论:
MyString1()
{
//no arg constructor
也许你的指示需要它,但总的来说这是一种比无用更糟糕的评论。从第一眼看代码时,评论应该告诉读者不是的事情。
char *string;
string = new char[0];
string[0] ='\0';
这会调用未定义的行为。允许使用零元素调用new,但是您不能取消引用它返回的内容(它可能返回空指针,或者它可能返回不引用任何存储的非空指针)。在大多数情况下,最好只将指针设置为NULL。
std::cout << string;
写出空字符串有什么意义?
size = 1;
字符串为空,因此通过正常计算,大小为零。
//constructor receives pointer to character array
仍然没用。
MyString1(char* chars)
由于您没有(或者不应该)计划修改输入数据,因此该参数应为char const *
。
{
int index = 0;
//Determine the length of the array
while (chars[index] != NULL)
index++;
虽然这有效,但“NULL”应该保留用作指针,至少是IMO。我写的是:
while (chars[index] != '\0')
++index;
除非您使用之前的值,否则更喜欢预增量到后增量。
//Allocate dynamic memory on the heap
与在堆上分配静态内存相反?
MyString1 MyString2;
对类型和变量使用相同的命名约定令人困惑。
while (string[index] != NULL)
以前适用于NULL的相同评论。
MyString1 append(MyString1 s)
IMO,这个函数的整个想法是完全错误的 - 如果你有一个字符串,并要求它在你的字符串中添加一些内容,它销毁你的原始字符串,并且(更糟)使它处于不可用的状态 - 当你开始添加一个释放字符串所拥有的内存的析构函数时,它将导致双重删除字符串的存储,该字符串是{{受害者?)的{{ 1}}呼吁它。
我会考虑编写一个私有的“复制”功能,并在你在这里展示的一些(大多数?)的实现中使用它。
作为一个更一般的建议,我会考虑更多的可能性:首先,我不会总是精确分配字符串所需的空间量,而是考虑将分配四舍五入到(例如)a两个人的力量。其次,如果您希望字符串类能够正常工作,您可以考虑实现“短字符串优化”。这包括在字符串对象本身的主体中为短字符串(例如20个字符)分配空间。由于许多字符串往往相对较短,因此如果字符串很短,可以通过避免执行堆分配来显着提高速度(并减少堆碎片等)。
答案 2 :(得分:1)
index
在追加函数的第二个while
循环中不会从0开始。您可能应该使用for
循环。哦,你正在使用错误的delete
形式。您应该使用delete[] string
,因为string
是一个数组。
还有很多其他风格问题和彻头彻尾的错误,但我首先提到的是您遇到的基本错误。
我会用这种方式编写append函数:
void append(MyString1 s)
{
//determine new size of the appended array and allocate memory
int newsize = s.size + size;
char *newstring = new char[newsize+1];
int destindex = 0;
for (int index = 0; index < size; ++index) {
newstring[destindex++] = string[index];
}
for (int index = 0; index < s.size; ++index) {
newstring[destindex++] = s.string[index];
}
newstring[destindex] = '\0';
delete[] string;
string = newstring;
}