我创建了这个简单的类:
class stringa
{
public:
char *Str;
stringa(const char *Value);
};
我的想法是你要为Stringa类创建一个对象,并将此对象用作字符串之类的东西。
我将构造函数定义如下:
stringa::stringa(const char *Value)
{
Str = new char;
int i = 0;
for(i = 0; Value[i] != '\0';i++)
{
Str[i] = Value[i];
Str[i+1] = '\0';
}
return;
}
一切都很好。我可以打电话:stringa S1 =" HelloPutAnythingHere&#34 ;;当它为这个类创建了多个对象时,问题就出现了。
我意识到如果第一个对象S1超过12个字符,并且我创建了另一个对象S2,则S1的结束字符不会出现。
所以,如果我有这个:
stringa S1 = "abcdefghijklmnopqrstuvwxyz0123456789";
stringa S2 = "br";
cout << S1.Str << endl << S2.Str;
只会显示: abcdefghijkl 和 br ,好像S1的其余部分已被彻底销毁。
我认为S2是在S1中间创建的。我添加的一些代码证实了这一点
S1的第一个字符(&#39; a&#39;)正在地址 0x8663008 创建,最后一个(&#39; \ 0&#39;)正在创建在地址 0x866302c 。虽然s2的第一个字符(&#39; b&#39;)是在 0x8663018 创建的,但该位置应包含字母&#39; q&#39;来自S1。
所以我的问题如下:如何在没有常量大小的情况下避免字符数组的叠加?我接近这个是不可能的?
我知道我可以使用字符串库,但这违背了我编写此代码的目的。
答案 0 :(得分:3)
Str = new char;
为一个字符分配足够的空间。因此,Str[0]
将是一个字符的有效引用,但任何Str[i]
的{{1}}都将是未定义的行为(除了您可以使用i > 0
的地址,只要你不要试图取消引用它。)
未定义的行为就是它所说的:undefined。对于Str[1]
的某些值,可能会发生由i
表示的存储未被任何其他对象使用的情况,因此您的程序似乎可以正常使用Str[i]
的值。或者可能会发生使用i
导致计算机迸发火焰的情况。 (注意:前者比后者更可能,但没有保证。)
您可以使用Str[3]
为len
字符分配足够的空间,但显然您需要知道Str = new char[len];
的值。而且,正如您所说,您可以使用各种库函数来简化此过程。
答案 1 :(得分:3)
您为Str
分配了一个字符:您必须分配一个字符数组。
您的程序有不确定的行为。
std :: string不需要常量大小,因为它在内部管理缓冲区,并根据需要重新分配,这基本上是你需要实现的。