C++ const引用
(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引用的更多相关文章
- C++ Const引用详解
(1) 在实际的程序中,引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的,我们可以定义一个指针引用. 1 int ival ...
- 【c++基础】const、const指针、const引用
一.const常量 声明时必须同时初始化(和“引用”一样) 二.const指针 三.const引用 引用本身和引用的对象都是const对象,可以用字面值来赋给const引用(普通引用则不行) ; co ...
- 传const引用代替传值
1.为什么使用传const引用? a.被调方法中,形参不再进行copy构造,以及析构,提高效率. b.传值,会出现对象切割的问题. 2.有没有例外? 在编译器底层,引用是使用指针实现的.这就意味着,如 ...
- const引用
在C++中可以声明const引用 const Type& name = var: const引用让变量拥有只读属性 const int &a = b const int &a ...
- c/c++ 拷贝控制 右值与const引用
拷贝控制 右值与const引用 背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收?? 1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收. Test t2 = ...
- const引用和函数占位参数遇上默认参数以及内联函数
1.const引用: 但是加上const之后是可以的,const int &a=100;就不会报错了. 2.函数占位参数: 如果给最后的占位参数加上默认值: 3.内联函数 内联只是对编译器发起 ...
- C++引用和const引用、常量指针、指针常量
1.引用.常量引用 引用主要被用做函数的形式参数--通常将类对象传递给一个函数. 引用在内部存放的是一个对象的地址,它是该对象的别名.引用不占用内存,因为取地址引用的值和被引用变量的地址相同.但是ob ...
- const引用返回值
一.引用 引用是别名 必须在定义引用时进行初始化.初始化是指明引用指向哪个对象的唯一方法. const 引用是指向 const 对象的引用: ; const int &refVal = iva ...
- 非const引用参数传入不同类型编译不过的理解(拒绝将临时对象绑定为非const的引用的形参是有道理的)
int f (int & I) { cout<<I<<std::endl; } void main() { long L; f(L); // 编译不过 f((int)L ...
- const引用与非const引用
void print1(int a) { cout<<a<<endl; } void print2(const int& a) { cout<<a<& ...
随机推荐
- YUYV&YV12&mtk6763
stImgInOut.stImgInfo.enImageType = UV_IMAGE_TYPE_YV12; stImgInOut.stImgInfo.as32Pitch[0] = pStreamIm ...
- scrapy docker 基本部署使用
1. 简单项目 pip install scrapy scrapy startproject appdemo 2. 项目代码 a. 项目代码结构 ├── Dockerfile ├── READ ...
- FastAdmin 开发时出错的调试
第一步:打开 FastAdmin Debug 打开 Debug. 第二步:打开浏览器控制器 打开浏览器控制器,并按 F5 重新加载页面. 第三步:在 network 查看详细错误信息 点击红色链接,可 ...
- js前台调用lodop打印
lodop简单介绍 lodop的打印功能已经非常强大,也在带web端的图形界面,可以供用户使用.使用js在前台调用lodop打印,一般分为两种方法: 1:特殊的指令打印,这种打印方式,是采用的与js无 ...
- (转)Android自定义属性时format选项( <attr format="reference" name="background" /> )
Android自定义属性时format选项可以取用的值 1. reference:参考某一资源ID. (1)属性定义: [html] view plaincopyprint? <declar ...
- MySQL 性能优化技巧
原文地址:MySQL 性能优化技巧 博客地址:http://www.extlight.com 一.背景 最近公司项目添加新功能,上线后发现有些功能的列表查询时间很久.原因是新功能用到旧功能的接口,而这 ...
- Android adb push 和 adb pull
将电脑 D 盘 libreference-ril.so 文件拷贝到安卓设备的 /system/lib 目录下 $ adb remount $ adb root $ adb push D:\libref ...
- 【转载】最短路径—Dijkstra算法和Floyd算法
注意:以下代码 只是描述思路,没有测试过!! Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始 ...
- Java的八种基本数据类型及其包装类
Java有八种基本数据类型,所谓基本类型就是说存储时仅存在栈中,那么与之相对就是引用类型,引用类型既存在栈里又存在堆里,栈内存放堆内地址. 八种基本类型分别为byte short int long f ...
- bc显示小数点前的0
bc是强大而常用的计算工具.不过在除法运算时,如果得到的结果值小于1,得到的小数前面的0不存.本篇提供几个常用小数点前缺0的解决方法. [root@maqing ~]# bc bc Copyright ...