您的位置:首页 > 其它

const 详解

2016-03-08 18:28 183 查看


零、文章来由

打算将基础知识在看书的同时系统的整理一下,方便大家也方便自己。整理的知识尽量参照书本知识,比网上获取的资料有更高的可信度。


一、从 文字常量和常变量 开始


1、文字常量

程序中的特殊标识符或表达式,由于同时满足:

(1)不可寻址(放在代码区)

(2)值不可变

所以可视为文字常量。他们是 静态数组名、枚举变量、全局(静态变量)首地址、#define定义的常量。

整型文字常量:

(1)前加0表示 八进制

(2)前加0x表示 十六进制

(3)后加L(推荐)或l,表示long类型

(4)后加U(或u)表示无符号数

eg.1024UL


2、常变量Const


同其他变量一样被分配空间,可寻址。

const是在高级语言的语义层面上定义的,是编译器在编译期做语法检测来保证,但是运行时,const变量不是在只读内存中,而是和一般变量一样放在数据区,所以一样可以对其进行修改。

所以:常变量是一种加了特殊限制的变量,理解成“只读”变量

即使是const修饰,也是可以修改的
<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> ShowValue(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> &i) {
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<i<<endl;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main()
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *p=(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *)&j;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *ptr=(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *)p;
(*ptr)++;
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//cout<<j<<endl; //还是会显示5,因为编译器优化的时候将j替换为文字常量5</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//但如果是int i=5; const int j=i; 则无法替换,直接输出j为6</span>
ShowValue(j); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//显示6</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>


3、常变量替换


如果常变量有初始化赋初值,那编译器将该常变量在其他地方替换成文字常量


但是如果开始不初始化就会错误

如:
<code class="language-c++ hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> DefineArray(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n){
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> B
={}; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//error,数组大小在编译期确定</span>
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(){
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> m=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> A[m]={}; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//ok</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>


4、文字常量和常变量寻址

<code class="language-c++ hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> &r=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//error,无法寻址文字常量,无法建立引用</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> &r=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//ok,在数据区开辟一个值为5的无名整数量,然后将引用r与这个整形两绑定</span>
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>


二、const用法


1、const的位置

<code class="language-c++ hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> *p; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指向常量的指针(即常指针,const修饰的是int),指向的对象是const型,不可以修改,但是指针p的指向可以修改</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> p; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指针常量(const修饰的是int*),指针变量p是const型,它的指向不可修改,但是指向的对象可以修改</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>


const和数据类型结合在一起 —>“常类型”。(看成一个整体)

修饰类型时,既可以放在放前面,也可以放在后面;用常类型声明 or 定义变量,const只出现在变量前。

const和被修饰类型间不能有其他标识符存在。

引用本身可以理解成一个指针常量

故在引用前使用const没有意义
<code class="language-c++ hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> & <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> r4=i; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//const是多余的,编译器warning后忽略const存在</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>


const配合二重指针,此例子中const在不同位置,结果不同
<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main()
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> **p1; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不是指针常量,指向 int count*(“int const*”是一个 指向整型常量的指针)</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> *p2; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不是指针常量,但所指的变量是指针常量(int *const,即指向整型的指针常量,指向不能修改)</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *ptr1=&i;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> ptr2=&j;

p1=&ptr1;
p2=&ptr2;

<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<**p1<<endl;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<**p2<<endl;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li></ul>


输出:

5

6上述p1和p2 赋值有讲究,如果 p1=&ptr2 或 p2=ptr1 就会编译错误


2、const修饰某个类 —> 常对象 和 常函数

const修饰对象–>常对象

const修饰成员函数—>常函数

在常函数中,不允许对任何成员变量进行修改

通过常对象,只能调用该对象的常函数
<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> A
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> num;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span>:
A() {num=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> disp();
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> disp() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">set</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n) {num=n;}

};

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> A::disp() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> {
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<num<<endl;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> A::disp() {
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"non-const version of disp()"</span><<endl;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main()
{
A a1;
a1.<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">set</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);
a1.disp();
A <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> a2;
a2.disp();
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li></ul>


以上注意:

(1)如果常函数声明和定义分开,都需要加const,否则编译错误

只有类的非静态成员函数可以被声明为常函数

(2)如果一个类的两个成员函数,返回值、函数名、参数列表完全相同,其中之一是const,则重载。因为 常成员函数的参数传入this指针是const Class*类型的,参数不同,导致函数签名不同。

非只读对象(如a1)调用某个函数(如 disp()),先找非const版本,如果没有,再调用const版本。而常对象,只能调用类中定义的常函数,否则编译器报错。

如果一个非const对象(如a1)调用函数,同时有const和非const版本的函数,我们希望其调用const函数。就必须建立该对象的常引用,或指向该对象的常指针来达到目的。如: (const A&)a1.disp(); 或 (const A *)&a1->disp();

(3)常对象创建后,其数据成员不允许在修改。所以显示构造函数来初始化该对象非常重要。

常对象,全体成员数据成员都是常量看待。

类对象的非静态常量成员必须在构造函数中初始化,且只能借助初始化列表进行。


3、const修饰函数参数+函数返回值

<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <iostream></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">using</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">namespace</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">std</span>;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> disp1(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> &ri){
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<ri<<endl;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> disp2(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i){
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<i<<endl;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> disp3(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>& ri){
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<ri<<endl;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ri;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>& disp4(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>& ri){
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<ri<<endl;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ri;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>& disp5(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>& ri){
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<ri<<endl;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ri;
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* argv[])
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> n=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;
disp1(n);
disp2(n);
disp3(n);
disp4(n)=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//修改引用返回值</span>
disp5(n);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//disp5(n)=6;是错误的</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li></ul>


注意:

(1)const修饰参数,主要作用是被引用对象或被指向对象,如果只是形参,就没有多少意义。如:void disp2(const int i),这里的i在函数中改不改变,加不加const没什么影响。

不但如此,同时定义一个相似的用const修饰参数和不用const修饰参数的函数,会引起重定义错误。比如:任何整型表达式的值,都可以传给int型参变量,也可以传给const int型参变量,故不重载。

(2)当返回值是一个普通数据,而非引用,const修饰也没多少意义。因为函数返回值是一个非左值,本来就不能改变其值。故其上 const int disp3(const int& ri),对返回值修饰然并卵。

(3)如果返回值为引用,用const修饰可以阻止对被引用对象修改,disp5(n)=6;是错误的

(4)常见的对const的误解。

误解一:用const修改的变量值一定是不能改变的。const修饰的变量可通过指针可间接修改。

如:
<code class="language-c++ hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *p=(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> *)&j;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *ptr=(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> *)p;
(*ptr)++;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>


误解二:常引用或常指针,只能指向常变量,这是一个极大的误解。常引用或者常指针只能说明不能通过该引用(或者该指针)去修改被引用的对象,至于被引用对象原来是什么性质是无法由常引用(常指针)决定的。


三、const_cast 的用法


1、作用


const_cast 是 C++ 运算符,作用是去除符合类型中的const或者volatile

当大量使用const_cast是不明智的,只能说程序存在设计缺陷。使用方法见下例:
<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> constTest(){
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"please input a integer:"</span>;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cin</span>>>i;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a=i;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>& r=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const_cast</span><<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>&>(a);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//若写成int& r=a;则发生编译错误</span>
++r;
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cout</span><<a<<endl;
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* argv[])
{
constTest();
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>


输入:

5

输出:

6

总结:

(1)const_cast运算符的语法形式是const_cast< type> (expression)。 括号不可省略

(2)const_cast只能去除目标的const或者volatile属性,不能进行不同类型的转换。只能将 const type* 转换为 type*,或者 const type & 转换为 type &。

如下转换就是错误的:
<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">cons tint A={<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>};
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* p=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const_cast</span>< <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>*>(A); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//不能由const int[]转换为char* </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>


(3)一个变量被定义为只读变量(常变量),那么它永远是常变量。cosnt_cast取消的是间接引用时的改写限制,而不能改变变量本身的const属性。 如下就是错误的:
<code class="language-c++ hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> j = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const_cast</span>< <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>> (i);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>


(4)利用传统的C语言中的强制类型转换也可以将 const type* 类型转换为 type* 类型,或者将 const type& 转换为 type& 类型。但是使用 const_cast 会更好一些,因为 const_cast 写法复杂(提醒程序猿不要轻易转换),转换能力较弱,目的明确,不易出错,易查bug;而C风格的强制类型转换能力太强,风险较大。


参考资料

[1]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: