(1)       在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用。

1 int ival = 1092;

2 int &re = ival;   //ok

3 int &re2 = &ival;   //错误

4 int *pi = &ival;

5 int *&pi2 = pi;   //ok

(2)       一旦引用已经定义,它就不能再指向其他的对象.这就是为什么它要被初始化的原因。

(3)       const引用可以用不同类型的对象初始化(只要能从一种类型转换到另一种类型即可),也可以是不可寻址的值,如文字常量。例如

double dval = 3.14159;

//下3行仅对const引用才是合法的

const int &ir = 1024;

const int &ir2 = dval;

const double &dr = dval + 1.0;

上面,同样的初始化对于非const引用是不合法的,将导致编译错误。原因有些微妙,需要适当做些解释。

引用在内部存放的是一个对象的地址,它是该对象的别名。对于不可寻址的值,如文字常量,以及不同类型的对象,编译器为了实现引用,必须生成一个临时对象,引用实际上指向该对象,但用户不能访问它。

例如:

double dval = 23;

const int &ri = dval;

编译器将其转换为:

int tmp = dval; // double -> int

const int &ri = tmp;

同理:上面代码

double dval = 3.14159;

//下3行仅对const引用才是合法的

const int &ir = 1024;

const int &ir2 = dval;

const double &dr = dval + 1.0;

内部转化为:

double dval = 3.14159;

//不可寻址,文字常量

int tmp1 = 1024;

const int &ir = tmp1;

//不同类型

int tmp2 = dval;//double -> int

const int &ir2 = tmp2;

//另一种情况,不可寻址

double tmp3 = dval + 1.0;

const double &dr = tmp3;

(4)       不允许非const引用指向需要临时对象的对象或值,即,编译器产生临时变量的时候引用必须为const!!!!切记!!

int iv = 100;

int *&pir = &iv;//错误,非const引用对需要临时对象的引用

int *const &pir = &iv;//ok

const int ival = 1024;

int *&pi_ref = &ival;    //错误,非const引用是非法的

const int *&pi_ref = &ival;   //错误,需要临时变量,且引用的是指针,而pi_ref是一个非常量指针

const int * const &pi_ref = &ival;  //正确

//补充

const int *p = &ival;

const int *&pi_ref = p;  //正确

(5)       ********对于const int *const & pi_ref = &iva; 具体的分析如下:*********

1.不允许非const引用指向需要临时对象的对象或值

int a = 2;

int &ref1 = a;// OK.有过渡变量。

const int &ref2 = 2;// OK.编译器产生临时变量,需要const引用

2.地址值是不可寻址的值

int * const &ref3 = &a;   // OK;

3.于是,用const对象的地址来初始化一个指向指针的引用

const int b = 23;

const int *p = &b;

const int *& ref4 = p;

const int *const & ref5 = &b;   //OK

const引用的语义到底是什么?

最后,我们可能仍然不明白const引用的这个const的语义是什么

const引用表示,试图通过此引用去(间接)改变其引用的对象的值时,编译器会报错!

这并意味着,此引用所引用的对象也因此变成const类型了。我们仍然可以改变其指向对象的值,只是不通过引用

下面是一个简单的例子:

1 #include <iostream>

2 using namespace std;

3

4 int main()

5 {

6     int val = 1024;

7     const int &ir = val;

8

9     val++;

10     //ir++;

11

12     cout << val << " " << ir << endl;

13

14     return 0;

15 }

其中第10行,如果我们通过ir来改变val的值,编译时会出错。但是我们仍然可以通过val直接改变其值(第9行)

总结:const引用只是表明,保证不会通过此引用间接的改变被引用的对象!

另外,const既可以放到类型前又可以放到类型后面,放类型后比较容易理解:

string const *t1;

const string *t1;

typedef string* pstring;string s;

const pstring cstr1 = &s;就出错了

但是放在类型后面不会出错:

pstring const cstr2 = &s;

from:http://blog.csdn.net/k2eats/archive/2008/06/12/2541790.aspx

C++ const引用的更多相关文章

  1. C++ Const引用详解

    (1)       在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用. 1 int ival ...

  2. 【c++基础】const、const指针、const引用

    一.const常量 声明时必须同时初始化(和“引用”一样) 二.const指针 三.const引用 引用本身和引用的对象都是const对象,可以用字面值来赋给const引用(普通引用则不行) ; co ...

  3. 传const引用代替传值

    1.为什么使用传const引用? a.被调方法中,形参不再进行copy构造,以及析构,提高效率. b.传值,会出现对象切割的问题. 2.有没有例外? 在编译器底层,引用是使用指针实现的.这就意味着,如 ...

  4. const引用

    在C++中可以声明const引用 const Type& name = var: const引用让变量拥有只读属性 const int &a = b const int &a ...

  5. c/c++ 拷贝控制 右值与const引用

    拷贝控制 右值与const引用 背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收?? 1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收. Test t2 = ...

  6. const引用和函数占位参数遇上默认参数以及内联函数

    1.const引用: 但是加上const之后是可以的,const int &a=100;就不会报错了. 2.函数占位参数: 如果给最后的占位参数加上默认值: 3.内联函数 内联只是对编译器发起 ...

  7. C++引用和const引用、常量指针、指针常量

    1.引用.常量引用 引用主要被用做函数的形式参数--通常将类对象传递给一个函数. 引用在内部存放的是一个对象的地址,它是该对象的别名.引用不占用内存,因为取地址引用的值和被引用变量的地址相同.但是ob ...

  8. const引用返回值

    一.引用 引用是别名 必须在定义引用时进行初始化.初始化是指明引用指向哪个对象的唯一方法. const 引用是指向 const 对象的引用: ; const int &refVal = iva ...

  9. 非const引用参数传入不同类型编译不过的理解(拒绝将临时对象绑定为非const的引用的形参是有道理的)

    int f (int & I) { cout<<I<<std::endl; } void main() { long L; f(L); // 编译不过 f((int)L ...

  10. const引用与非const引用

    void print1(int a) { cout<<a<<endl; } void print2(const int& a) { cout<<a<& ...

随机推荐

  1. BZOJ4543 [POI2014]Hotel加强版

    题意 有一个树形结构,每条边的长度相同,任意两个节点可以相互到达.选3个点.两两距离相等.有多少种方案? 数据范围:n<=100000 分析 参照小蒟蒻yyb的博客. 我们先考虑一个\(O(n^ ...

  2. js中对数字进行正则判断

    <script type="text/javascript"> function SubmitCk(num) { var reg = /^([a-zA-Z0-9]+[_ ...

  3. 7个GIF动图帮你瞬间理解三角函数

    7个GIF动图帮你瞬间理解三角函数 蝌蚪五线谱 百家号04-2120:53 图片来源:IMGUR 三角函数是数学中研究三角形的一个分支,专门阐述三角形的角度和对应边的关系. 有趣的是,定义边角关系的三 ...

  4. smarty 模板编译和变量调节器 模板引入

    <?php require './smarty/Smarty.class.php'; $sm = new Smarty; //$sm->force_compile = true; $sm- ...

  5. JDK1.5java新特性

    JDK1.5java增加的新特性: 自动装箱/拆箱      增强for     泛型      枚举      静态导入      可变参数 1 自动装箱/拆箱 * JDK1.5允许开发人员把一个基 ...

  6. vi配置

    1.配置文件的位置在目录 /etc/ 下面,有个名为vimrc的文件,这是系统中公共的vim配置文件,对所有用户都有效.而在每个用户的主目录下,都可以自己建立私有的配置文件,命名为:“.vimrc”. ...

  7. Unit01: JDBC原理 、 JDBC基础编程

    Unit01: JDBC原理 . JDBC基础编程 这个文件里面有两块内容: 1.用比较麻烦的方式连接数据库,test1(),test4() 2.创建DBTool,测试DBTool连接数据库 ,tes ...

  8. php 常用方法

    //返回json数据给js function json_output($err_code = 0 , $error_message = '' , $data = [] , $redirect = '' ...

  9. SecureCRT上传下载文件教程(Zmodem使用教程)

    SecureCRT是一个仿真终端连接工具.它可以方便的连接SSH服务器,远程管理Linux.同时,它还能使用多种协议方便的上传下载文件.其中Zmodem是SecureCRT支持比较好的一种古老的上传下 ...

  10. Java运算符,算术运算符

    算术运算符介绍 算术运算符用在数学表达式中,它们的作用和在数学中的作用一样. 下表列出了所有的算术运算符. 表格中的实例假设整数变量A的值为10,变量B的值为20: 操作符 描述 例子 + 加法 - ...