effective c++中M21的一个例子 总是运行不了
class string
{ public:
string(char *_data):data(_data)
{}
// 用于非const对象的operator[]
char& operator[](int position)
{
return data[position];
}
// 用于const对象的operator[]
const char& operator[](int position) const
{
return data[position];
}
private: char *data;
};
string s1 = "hello"; cout << s1[0]; // 调用非const // string::operator[] const string s2 = "world"; cout << s2[0]; // 调用const // string::operator[]
通过重载operator[]并给不同版本不同的返回值,就可以对const和非const string进行不同的处理:
string s = "hello"; // 非const string对象
cout << s[0]; // 正确——读一个 // 非const string
s[0] = 'x'; // 正确——写一个 // 非const string ---------》问题就在这里,会出现读取错处指针
const string cs = "world"; // const string 对象
cout << cs[0]; // 正确——读一个 // const string
cs[0] = 'x'; // 错误!——
上面的读取操作正确,但是无论对象是否为const都无法对其进行写操作,上面的数据指针在测试范围内有效
[解决办法]
s变量哪里定义的
[解决办法]
写??你指的是cin吗?
是的话要重载>>
[解决办法]
string s = "hello"; 这里"hello"是const char *类型,是不允许修改的。
这样试试看:
char s1[] = "hello";
string s = s1;
[解决办法]
1.c++ 标准规定 string literal 的类型是 array of n const char,其中 n 为字符串长度。
2.c++ 标准规定任何试图修改 const 内容的程序导致 undefined behavior.
因此,cs[0] = 'x',试图写该 "hello" 的第一个字节,后者为 string literal 具有 const 类型,所以赋值操作导致 undefined behavior,引发错误。
[解决办法]
这时我今天加入csdn里的第一条回复贴,多多指教!
你把类里面那个重载的函数const char& operator[](int position) const前面的那个const去掉看看,它指向的对象就可以改变了。
[解决办法]
当然要崩溃了,你通过改变自己的特性就像改变别人,这都让你得逞,那就没安全可言了。
问题实质:显然你这里是“浅拷贝”(Google下吧,对你进一步理解有帮助),只是将自身声明的字符指针用另一个指向一个字符串常量的字符指针进行了赋值。你的实现等同于下面的语句:
// 下面三条等同于构造你的string对象
char *chPtr;
const char *cchPtr = "abcde";
chPtr = (char*)cchPtr;
// 等同于你用重载下标赋值
chPtr[0] = 'A';
你觉得能行么?显然是不允许的,你的重载只是对你本身的数据才有效果(你本身是char*),但不能改变别的数据的属性(即本身就是const的字符串常量)。当然,你想改得话,要么将别人的数据拷贝过来(在构造函数中实现数据拷贝),要不就指向可以改变的字符串。下面给出示例:
- C/C++ code
#include <iostream>using std::cin;using std::cout;using std::endl;class string{public: string(char *_data):data(_data) { } /* // 对应方法2: 字符数组定义可以更改的字符串 ======================== string(const char *_data) { data = NULL; int len = strlen(_data); if (len != 0) { data = new char[len+1]; strcpy(data, _data); } } ~string() { if (data != NULL) { delete [] data; } } // 方法2结束 ========================================= */ // 用于非const对象的operator[] char& operator[](int position) { return data[position]; } // 用于const对象的operator[] const char& operator[](int position) const { return data[position]; } private: char *data; };int main(){ string s1 = "hello"; cout << s1[0] << endl; // 调用非const下标重载运算符 string::operator[] const string s2 = "world"; cout << s2[0]; // 调用const下标重载运算符 const string::operator[] // 通过重载operator[]并给不同版本不同的返回值,就可以对const和非const string进行不同的处理 // 对应方法1: 字符数组定义可以更改的字符串 ======================== char chArray[] = {'h', 'e', 'l', 'l', 'o', '\0'}; string s = chArray; // 非const string对象 cout << s[0] << endl; // 正确 —— 读一个非const string s[0] = 'x'; // 正确 —— 写一个非const string const string cs = chArray; cout << cs[0] << endl; // 正确 —— 读一个非const string //cs[0] = 'x'; // 错误 —— 写一个 const string // 方法1结束 ========================================= /* // 对应方法2: 通过拷贝字符串常量到类变量中来实现更改 ==================== string s = "hello"; // 非const string对象 cout << s[0] << endl; // 正确 —— 读一个非const string s[0] = 'x'; // 正确 —— 写一个非const string const string cs = "hello"; cout << cs[0] << endl; // 正确 —— 读一个非const string //cs[0] = 'x'; // 错误 —— 写一个 const string // 方法2结束 ========================================= */ cin.get(); return 0;}