const用法小结
2013-08-29 13:47
120 查看
定义格式:(1) const 类型名 变量名 =常量或者常量表达式;
(2) 类型名 const 变量名 = 常量或者常量表达式;
如: const int iVal = 8;
iVal= 10;//错误,不允许更改
2. const引用:指向const对象的引用。
定义格式:(1)const <类型说明符> &<变量名> =
…
(2)<类型说明符> const &<变量名> =
…
普通引用不能绑定到const 对象,但const 引用可以绑定到非const 对象。
const int iVal = 8;
int &p = iVal; //错误
const int &p = iVal; //正确
非const 引用只能绑定到与该引用同类型的对象。
const 引用则可以绑定到不同但相关的类型的对象或绑定到右值。
(1) constint &r = 100; // 绑定到字面值常量
(2) inti = 50;
const int &r2 = r + i; // 引用r绑定到右值
(3) doubledVal = 3.1415;
const int &ri = dVal; // 整型引用绑定到double 类型
编译器会把以上代码转换成如下形式的编码:
int temp= dVal; // 创建临时变量
const int&ri = temp; // 把引用指向临时变量
3. const修饰指针:
(1) 指向const对象的指针:指针本身可以重新指向,但是所指向的内容不能修改。
定义格式:const <类型说明符> *<变量名>
<类型说明符> const *<变量名>
允许把非const 对象的地址赋给指向const
对象的指针:
int iVal;
const int*p = &iVal;
iVal = 10;
*p = 11; //错误 此时*p 是只读的,不能修改其值。
如何将一个const
对象合法地赋给一个普通指针???
例如:
const doubledVal = 3.14;
double*ptr = &dVal; // 错误
double*ptr = const_cast<double*>(&dVal);
// const_cast是C++中标准的强制转换,C语言使用:double *ptr = (double*)&dVal;
(2).const 指针:指针指向不能改变
声明或定义的格式如下(定义时必须初始化):
<类型说明符> *const <变量名> = ……
例如:
int iVal1=0;
int iVal2= 10;
int *constp = &iVal;
p = &iVa2l;//错误 指针的指向不能被修改。
*p = 1;// 正确 指针所指向的基础对象可以修改。
(3) 指向const 对象的const 指针:指针本身和指向的内容均不能改变
声明或定义的格式如下(定义时必须初始化):
const <类型说明符> *const <变量名> = ……
例如:
const doublepi = 3.14159;
const doubledVal = 3.14;
const double*const pi_ptr = π
pi_ptr= &dVal; // 错误指针的指向不能被修改。
*pi_ptr= dVal; // 错误指针所指向的基础对象也不能被修改。
4. const 修饰一般函数
(1) 修饰函数参数
void func1(const int i); // i不能被修改
void func3 (const A &rA); // rA所引用的对象不能被修改
void func2 (const char *pstr); // pstr所指向的内容不能被修改
(2) 修饰函数的返回值
返回值:const int func1(); // 此处返回int 类型的const值,意思指返回的原函数里的变量的初值不能被修改,但是函数按值返回的这个变量被制成副本,能不能被修改就没有了意义,它可以被赋给任何的const或非const类型变量,完全不需要加上这个const关键字。
[注意]但这只对于内部类型而言(因为内部类型返回的肯定是一个值,而不会返回一个变量,不会作为左值使用,否则编译器会报错),对于用户自定义类型,返回值是常量是非常重要的(后面在类里面会谈到)。
返回引用:const int &func2(); // 注意千万不要返回局部对象的引用,否则会报运行时错误:因为一旦函数结束,局部对象被释放,函数返回值指向了一个对程序来说不再有效的内存空间。
返回指针:const int *func3(); // 注意千万不要返回指向局部对象的指针,因为一旦函数结束,局部对象被释放,返回的指针变成了指向一个不再存在的对象的悬垂指针。
5. const 在类中的使用
class A
{
public:
void func();
void func() const;
const A operator+(const A &) const;
private:
int num1;
mutable int num2;
const size_t size;
};
(1) 修饰成员变量
const size_tsize; // 对于const的成员变量,[1]必须在构造函数里面进行初始化;[2]只能通过初始化成员列表来初始化;[3]试图在构造函数体内对const成员变量进行初始化会引起编译错误。
例如:
A::A(size_tsz):size(sz) // ok:使用初始化成员列表来初始化
{
}
A::A(size_tsz)
(2) 修饰类成员函数
void func()const; // const成员函数中不允许对数据成员进行修改,如果修改,编译器将报错。如果某成员函数不需要对数据成员进行修改,最好将其声明为const 成员函数,这将大大提高程序的健壮性。
const 为函数重载提供了一个参考
class A
{
public:
void func(); // [1]
void func() const; // [2]:上一个函数[1]的重载
……
};
A a(10);
a.func();// 调用函数[1]
const Ab(100);
b.func();// 调用函数[2]
如何在const成员函数中对成员变量进行修改???
mutable
class A
{
public:
A::A(int i):m_data(i){}
void SetValue(int i) const { m_data = i; }
private:
mutable int m_data; // 这里处理
};
(3)修饰类对象
const Aa; // 类对象a 只能调用const 成员函数,否则编译器报错。
(4)修饰类成员函数的返回值
const Aoperator+(const A &) const; // 前一个const 用来修饰重载函数operator+的返回值,可防止返回值作为左值进行赋值操作。
例如:
A a;
A b;
A c;
a + b =c; // 出错: 如果在没有const 修饰返回值的情况下,编译器不会报错。
C和C++中const区别
1.只读变量 &常量
在C语言中,被const修饰的就是常量吗?真的能不动如山吗?编译如下代码,你觉得如何?
const int a = 10;
int *pa = &a;
*pa = 20;
printf("%d/n",*pa);
printf("%d/n",a);
编译器并不会像你想的那样会报错,只是给出警告(warning C4090: “初始化”: 不同的“const”限定符)你运行时才发现,a的值已经被改掉了。变成了 20
关键字const并不能把变量变成常量!在一个符号前面加上限定符const只是表示不能被赋值,换句话说,它的值对这个符号来说是只读的,但是并不能防止通过程序的内部(或者说外部)的方法来修改这个值。
所在C语言中被const修饰的变量只是一个只读的变量而已。如:
const intn = 100;
int a
;(C不提倡这样写,可以用宏代替)
但是在C++中不是这样的,在C++中被const的修饰毫无疑问是常量,它的值在编译时就被确定了。
const int a = 10;
int *pa = &a;
*pa = 20;
printf("%d/n",*pa);
上面代码在C++中是错误的,肯定会出现编译错误。( error C2440: “初始化”: 无法从“const int *”转换为“int *” )
而下面代码在C++中是很普遍的。
const intn = 100;
int a
;
而且这样的表达是很普遍的很值得提倡的表示法(C++中不提倡使用宏,宏可以被常量、内联函数替代)。
在C++中的const属性是可以被去掉的,通过const_cast就可以强转掉。你试过这样的代码吗?
#include<iostream>
using namespacestd;
int main()
{
const int a = 10;
const int *pa = &a;
int* pb = const_cast<int*>(pa);
*pb = 20;
cout << *pa << endl;
cout << *pb << endl;
cout << a << endl;
return 0;
}
输出结果为
20
20
10
2. 内连接和外连接的区别
const variable 在定义时必须初始化,是文件内部可见。这是因为c++中,const变量默认是内连接的(internal linkage)。(原因见后)
也就是说它只能在定义它的文件内部使用,连接时其它编译单元看不见它。例如:
const int i = 0 ; // 而且编译器一般不为const variable分配内存,而是将它放符号表(symbol table),以便编译时实现常量折叠(constant folding)。
但是,若是进行如下定义:extern const int i;
则将强制编译器为变量分配内存空间。因为,extern 意味着使用外部链接(external linkage)。
当你对一个const variable 取地址时,也会进行内存分配。例如:
const int i = 9;
long address = (long ) &i;
由上面我们可以看出,编译器并不总是能够成功的避免为常量分配内存,上述两种情况就必须分配内存。所以const variable如果默认是外连接,就有可能导致同一个常量在不同的cpp文件中都分配了内存(比如多个文件中都要求取得一个常量的地址)。这就会让编译器认为同一常量出现重复定义而报错。
而如果常量默认为内连接,这就意味着该常量只在当前定义它的文件内部有效,而连接器不会试图去连接其他编译单元里的常量。这样,即使多个cpp文件中有相同名字的一个常量也不会发生冲突。如此,编译器就可有效的实现常量折叠(constant folding)
另外,有上面我们知道,在C++中,const int i = 0; i的值是在符号表里,这就意味着i的值是编译期间可见的。所以,如下代码是可行的:
const int i = 0;
const int j = i + 1; // ok! 因为i的值在编译时知道,j也是const
这里和C中的const有所不同,C中的const默认为外连接,所以总是会为其分配内存空间。这就意味着,在C中
const int bufsize = 100;
在编译期间,编译器并不知道 bufsize的值。所以,下面的代码有误:
const int bufsize = 100;
char buf[bufsize]; // error
还有一点不同的是:
const int bufsize;
这句代码在C中是可以的,编译器认为这是一个声明,某处有为这个常量分 配内存,但是在C++中,这句代码是不可以的。
可以有两种方式修改:
(1) const int bufsize = 100; //定义时初始化
(2) extern const int; // 当然,这句在C中也是可以的
////////////////////////////////////////////////////////////////////////////////////
在C语言中:
const int size;
这个语句是正确的,因为它被C编译器看作一个声明,指明在别的地方分配存储空间.但在C++中这样写是不正确的.C++中const默认是内部连接,如果想在C++中达到以上的效果,必须要用extern关键字.
C++中,const默认使用内部连接.而C中使用外部连接.
内连接:编译器只对正被编译的文件创建存储空间,别的文件可以使用相同的表示符或全局变量.C/C++中内连接使用static关键字指定.
外连接:所有被编译过的文件创建一片单独存储空间.一旦空间被创建,连接器必须解决对这片存储空间的引用.全局变量和函数使用外部连接.通过extern关键
字声明,可以从其他文件访问相应的变量和函数.
************************C++代码******************************
header.h
const int test = 1;
test1.cpp
#include
#include "header.h"
using namespace std;
int main()
{
cout << "in test1 :" << test << endl;
}
test2.cpp
#include
#include "header.h"
using namespace std;
void print()
{
cout << "in test2:" << test << endl;
}
以上代码编译连接完全不会出问题,但如果把header.h改为:
extern const int test = 1;
在连接的时候,便会出现以下错误信息:
test2 error LNK2005: "int const test" (?test@@3HB) 已经在 test1.obj 中定义
因为extern关键字告诉C++编译器test会在其他地方引用,所以,C++编译器就会为test创建存储空间,不再是简单的存储在名字表里面.所以,当两个文件同时包含header.h的时候,会发生名字上的冲突.
此种情况和C中const含义相似:
header.h
const int test = 1;
test1.c
#include
#include "header.h"
int main()
{
printf("in test1:%d\n",test);
}
test2.c
#include
#include "header.h"
void print()
{
printf("in test2:%d\n",test);
}
错误消息:
test3 fatal error LNK1169: 找到一个或多个多重定义的符号
test3 error LNK2005: _test 已经在 test1.obj 中定义
C++中,是否为const分配空间要看具体情况.
如果加上关键字extern或者取const变量地址,则编译器就要为const分配存储空间。
相关文章推荐
- Const用法小结 (选择自 yuguanglou 的 Blog)
- const 用法小结
- C++中const用法小结
- c / c++ const 用法小结
- const在基本数据类型和指针类型中的用法小结
- const用法小结
- const用法小结
- const用法小结
- Const用法小结
- Const用法小结[转载]
- C/C++中const用法小结
- C++中 Const用法小结(转载)
- const用法小结
- Const用法小结 (转)
- Const用法小结
- Const用法小结
- C++中常见const用法小结
- C++中const、volatile、mutable用法小结
- const的用法小结
- c++中const用法小结