回复 末离 的《关于C++的小问题》
关于c++的小问题,char *a="hello" 和char a[]="hello"
两者的区别是什么,
在实际应用中,有什么不同吗?
char *a="hello" 和char a[]="hello"
在char *a = "hello"里 a 是一个字符型针指变量,在编译这一句时,"hello"是一个字符串常量.本质是一个字符数组,但是每一个数组的无数是一个常量; a 就是指向的这个字符数组的第一个元素的存储地址.你可以通过用*(a + i)或者a[ i ] 去访问这个字符串里的每一个元素,但是你不能去用*(a + i) = ' a ' 或者 a[ i ] = ' b ' 去更改任何一个元素的值.在VC++里面, 因为一个字符指针直接赋值一个字符串,而这个字符串是一个常量,所以有下面这个特点:
char *a = "hello";
char *b = "hello";
由于"hello"是一个字符串常量,两条语句的字符串是一样的,所以这时,编译器给开辟了一次"hello"的存储空间, 让a 和 b 都指向这唯一一个"hello"的第一个元素存储的空间,所以a 和 b 是相等的.只要两个字符串有一点点的不同,则a 和 b 就是不相等的了.这样做,节约了空间,因为a 和 b 都是指向的量常,你本来就不能用a 和 b 去做修改字符串的操作,所以这样做是很好的.
在 char a[ ] = "hello" 里, a 就是一个数组名, 它的本质上相当于一个字符型的常量指针, 但是和碎片大哥说的一样,这个a在汇编以后是没有一个空间来存储它的, a 本身表示的就是一个地址, a 相当于一个地址的引用, 用a 去访问元素的时候是属于直接用地址去访问(也就是直接访问).a 所代表的地址是这个数组元素的第一个元素存储的地址,注意a 是代表了这个地址,而不是指向这个地址. 所以以后就不能做些想将a 所代表的地址更改的事了, 但是这个数组的每一个元素都是变量,所以你可以用*(a + i) 或 a[ i ]去访问更改元素的值.
从上面的比较我们可以看出数组和指针之间是有很大的 联系的.我们就可以想到String 类一般会是怎么设计的.
#include "stdafx.h"
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
class String
{
public:
String()
{
ptr = NULL;
length = 0;
}
String(char *p)
{
length = strlen(p);
ptr = new char[length + 1]; // 最后会有一个空字符
strcpy(ptr, p);
ptr[length] = '/0';
}
// 重载 = 运算符
const String &operator = (const char *p)
{
if (ptr != NULL)
{
delete []ptr;
length = 0;
}
length = strlen(p);
ptr = new char[length + 1]; // 最后会有一个空字符
strcpy(ptr, p);
ptr[length] = '/0';
return *this;
}
// 重载 [] 运算符 此处用来改变字符串的某一元素的值
char &operator [] (int subscript)
{
if(subscript < 0 || subscript >= length)
{
cerr << "/n错误: 下标 " << subscript
<< "越界!" << endl;
exit(1);
}
return ptr[subscript]; // 此处把字符串里你想改的元素的引用返回给你了,所以你就可以去更改它的值
}
// 重载 [] 运算符 此处用来访问字符串的某一元素的值
char operator [] (int subscript) const
{
if(subscript < 0 || subscript >= length)
{
cerr << "/n错误: 下标 " << subscript
<< "越界!" << endl;
exit(1);
}
return ptr[subscript]; //此处只是把字符串里你想改的元素的值返回了.
}
~String()
{
if (ptr != NULL)
{
delete []ptr;
}
}
private:
char *ptr;
int length;
};
int main(int argc, char* argv[])
{
String theString("Who are you?");
cout << theString[2] << endl;
theString = "Hymrjgc";
cout << theString[2] << endl;
return 0;
}
我只是简单的写了几个成员函数,大家可以加很多的,自己也可以做到像STL JAVA MFC C#里面的String 类型那样好。
不过我们在实际应用中,最好就用人家给我们的现成的好了,只是我们应该去了解明白他们可能是怎么去设计的。
两者的区别是什么,
在实际应用中,有什么不同吗?
char *a="hello" 和char a[]="hello"
在char *a = "hello"里 a 是一个字符型针指变量,在编译这一句时,"hello"是一个字符串常量.本质是一个字符数组,但是每一个数组的无数是一个常量; a 就是指向的这个字符数组的第一个元素的存储地址.你可以通过用*(a + i)或者a[ i ] 去访问这个字符串里的每一个元素,但是你不能去用*(a + i) = ' a ' 或者 a[ i ] = ' b ' 去更改任何一个元素的值.在VC++里面, 因为一个字符指针直接赋值一个字符串,而这个字符串是一个常量,所以有下面这个特点:
char *a = "hello";
char *b = "hello";
由于"hello"是一个字符串常量,两条语句的字符串是一样的,所以这时,编译器给开辟了一次"hello"的存储空间, 让a 和 b 都指向这唯一一个"hello"的第一个元素存储的空间,所以a 和 b 是相等的.只要两个字符串有一点点的不同,则a 和 b 就是不相等的了.这样做,节约了空间,因为a 和 b 都是指向的量常,你本来就不能用a 和 b 去做修改字符串的操作,所以这样做是很好的.
在 char a[ ] = "hello" 里, a 就是一个数组名, 它的本质上相当于一个字符型的常量指针, 但是和碎片大哥说的一样,这个a在汇编以后是没有一个空间来存储它的, a 本身表示的就是一个地址, a 相当于一个地址的引用, 用a 去访问元素的时候是属于直接用地址去访问(也就是直接访问).a 所代表的地址是这个数组元素的第一个元素存储的地址,注意a 是代表了这个地址,而不是指向这个地址. 所以以后就不能做些想将a 所代表的地址更改的事了, 但是这个数组的每一个元素都是变量,所以你可以用*(a + i) 或 a[ i ]去访问更改元素的值.
从上面的比较我们可以看出数组和指针之间是有很大的 联系的.我们就可以想到String 类一般会是怎么设计的.
#include "stdafx.h"
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
class String
{
public:
String()
{
ptr = NULL;
length = 0;
}
String(char *p)
{
length = strlen(p);
ptr = new char[length + 1]; // 最后会有一个空字符
strcpy(ptr, p);
ptr[length] = '/0';
}
// 重载 = 运算符
const String &operator = (const char *p)
{
if (ptr != NULL)
{
delete []ptr;
length = 0;
}
length = strlen(p);
ptr = new char[length + 1]; // 最后会有一个空字符
strcpy(ptr, p);
ptr[length] = '/0';
return *this;
}
// 重载 [] 运算符 此处用来改变字符串的某一元素的值
char &operator [] (int subscript)
{
if(subscript < 0 || subscript >= length)
{
cerr << "/n错误: 下标 " << subscript
<< "越界!" << endl;
exit(1);
}
return ptr[subscript]; // 此处把字符串里你想改的元素的引用返回给你了,所以你就可以去更改它的值
}
// 重载 [] 运算符 此处用来访问字符串的某一元素的值
char operator [] (int subscript) const
{
if(subscript < 0 || subscript >= length)
{
cerr << "/n错误: 下标 " << subscript
<< "越界!" << endl;
exit(1);
}
return ptr[subscript]; //此处只是把字符串里你想改的元素的值返回了.
}
~String()
{
if (ptr != NULL)
{
delete []ptr;
}
}
private:
char *ptr;
int length;
};
int main(int argc, char* argv[])
{
String theString("Who are you?");
cout << theString[2] << endl;
theString = "Hymrjgc";
cout << theString[2] << endl;
return 0;
}
我只是简单的写了几个成员函数,大家可以加很多的,自己也可以做到像STL JAVA MFC C#里面的String 类型那样好。
不过我们在实际应用中,最好就用人家给我们的现成的好了,只是我们应该去了解明白他们可能是怎么去设计的。