我考,我信心苦苦码了这么多次,加上自己见解,好好的写了很多,结果最后发布时居然。。。。没成功。
然后我那可怜的字都没了,我哭,
喷血的保存,写了这么长时间的东西就这么没了
这次没耐心了,只能赋值其他的有点用的拉上去了。。。。
char *p = "hello"; // 非const指针,
// 非const数据
const char *p = "hello"; // 非const指针,
// const数据
char * const p = "hello"; // const指针,
// 非const数据
const char * const p = "hello"; // const指针,
// const数据
记住的方法,除去类型名即char ,然后看下const修饰的是什么
const char *p = "hello"; const修饰*p,即修饰p指向的内容数据 ,const数据
char * const p = "hello"; const修饰p,即修饰p指针本身。const指针
语法并非看起来那么变化多端。一般来说,你可以在头脑里画一条垂直线穿过指针声明中的星号(*)位置,如果const出现在线的左边,指针指向的数据为常量;如果const出现在线的右边,指针本身为常量;如果const在线的两边都出现,二者都是常量。
在指针所指为常量的情况下,有些程序员喜欢把const放在类型名之前,有些程序员则喜欢把const放在类型名之后、星号之前。所以,下面的函数取的是同种参数类型:
class widget { ... };
void f1(const widget *pw); // f1取的是指向
// widget常量对象的指针
void f2(widget const *pw); // 同f2
因为两种表示形式在实际代码中都存在,所以要使自己对这两种形式都习惯。
const的一些强大的功能基于它在函数声明中的应用。在一个函数声明中,const可以指的是函数的返回值,或某个参数;对于成员函数,还可以指的是整个函数。
=----------------
const成员函数的目的当然是为了指明哪个成员函数可以在const对象上被调用。但很多人忽视了这样一个事实:仅在const方面有不同的成员函数可以重载。这是c++的一个重要特性。再次看这个string类:
class string {
public:
...
// 用于非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 string
另外注意,这里的错误只和调用operator[]的返回值有关;operator[]调用本身没问题。 错误产生的原因在于企图对一个const char&赋值,因为被赋值的对象是const版本的operator[]函数的返回值。
还要注意,非const operator[]的返回类型必须是一个char的引用——char本身则不行。如果operator[]真的返回了一个简单的char,如下所示的语句就不会通过编译:
s[0] = 'x';
因为,修改一个“返回值为固定类型”的函数的返回值绝对是不合法的。即使合法,由于c++“通过值(而不是引用)来返回对象”(见条款22)的内部机制的原因,s.data[0]的一个拷贝会被修改,而不是s.data[0]自己,这就不是你所想要的结果了。
一般用const修饰返回值为对象本身的情况多用于二目操作符重载函数并产生新对象的时候。
[总结] 一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。
原因如下:
如果返回值为某个对象为const或某个对象的引用为const ,则返回值具有const属性,则返回实例只能访问类a中的公有数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
const 限定函数的值型返回值:
const int Fun1();
const MyClass Fun2();
分析:上述写法限定函数的返回值不可被更新,当函数返回内部的类型时(如Fun1),已经是一个数值,当然不可被赋值更新,所以,此时const无意义, 最好去掉,以免困惑。当函数返回自定义的类型时(如Fun2),这个类型仍然包含可以被赋值的变量成员,所以,此时有意义。
使用const的一些建议
1 要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;
2 要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;
3 在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;
4 const在成员函数中的三种用法要很好的使用;
5 不要轻易的将函数的返回值类型定为const;
6 除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;