c++中const类型的使用与注意事项
2013-02-26 18:09
381 查看
常量是标识符他在程序运行期间是恒定不变的,在c语言中可以用#define来定义一个常量,称为宏常量。c++中除了宏常量还可以用const来定义常量。
常量为什么存在和存在的意义, 如果不使用常量,直接在程序中填写数字或字符串,将会有什么麻烦?
(1) 程序的可读性(可理解性)变差。程序员自己会忘记那些数字或字符串是什么意
思,用户则更加不知它们从何处来、表示什么。
(2) 在程序的很多地方输入同样的数字或字符串,难保不发生书写错误。
(3) 如果要修改数字或字符串,则会在很多地方改动,既麻烦又容易出错。
一、const修饰普通变量和指针变量
const 修饰变量有两种方式:
const TYPE value;
TYPE const value;
这两种写法本质上是相同的,对于一个非指针的类型TYPE,无论怎么写,都是一个含义,即value值不可变。
但是对于指针类型的TYPE,不同的写法会有不同情况:
(1)指针本身是常量不可变
(char*) const p;
(2)指针所指向的内容是常量不可变
const (char) *p;
(char) const *p;
(3)两者都不可变
const char* const p;
识别const到底是修饰指针还是指针所指的对象,还有一个较为简便的方法,也就是沿着*号划一条线:
如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。
二、const修饰函数参数
用const修饰函数的参数用途非常广泛,也使程序更安全更高效。被声明为const类型的变量在函数体内不容许被改变。
int function(const int val) // val在函数体内不容许改变
int function(const char* val) //val 所指向的内容在函数体内不容许改变
int function(char* const val) // 指针变量val本身是常量 在函数体内的指向不容许改变
int function(const class &val ) // 引用类型在函数体内不许改变
经常在函数传递阐述的时候会使用引用类型是因为,如果该类型是自定的不是系统自带的基本数据类型,如果函数采取的是非引用(值传递),函数会产生临时变量并赋值该变量的至这样影响了函数调用的效率,因此在函数参数传递的过程中经常采用的是传引用。
三、const修饰类对象、对象指针、对象引用
const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
class A
{
public :
int func1();
int func2() const;
};
const A obj;
obj.func1();//error 不能调用非const函数
obj.func2();// ok
const A* obj;
obj->func1();//error
obj->func2();//ok
四、const修饰数据成员
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么,例如:
class A
{
const int size = 100; //错误
int array[size]; //错误,未知的size
}
const数据成员的初始化只能在类的构造函数的初始化列表中进行。
class A
{
A(int size);
const int SIZE;
};
A::A(int size):SIZE(size)
{}
要想建立在整个类中都恒定的常量,可以用类中的枚举常量来实现,例如:
class A
{
…
enum {size1=100, size2 = 200 };
int array1[size1];
int array2[size2];
…
}
枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。
五、const修饰成员函数
const修饰类的成员函数,用const修饰的成员函数不能改变对象的成员变量。一般把const写在成员函数的最后:
class A
{
int func() const;
};
对于const类对象/指针/引用,只能调用类的const成员函数。
六、const修饰成员函数的返回值
1、一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回const对象,或返回const对象的引用,则返回值具有const属性,返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
2、如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针所指的内容)不能被修改,该返回值只能被赋给加const 修饰的同类型指针:
const char * GetString(void);
如下语句将出现编译错误:
char *str=GetString();
正确的用法是:
const char *str=GetString();
3、函数返回值采用“引用传递”的场合不多,这种方式一般只出现在类的赙值函数中,目的是为了实现链式表达。如:
class A
{
…
A &operate= (const A &other); //赋值函数
}
A a,b,c; //a,b,c为A的对象
…
a=b=c; //正常
(a=B)=c; //不正常,但是合法
若赋值函数的返回值加const修饰,那么该返回值的内容不允许修改,上例中a=b=c依然正确。(a=b)=c就不正确了。
还有在重载输入输出流操作符的时候也是这种情况<<, >>。
七 const常量与define宏定义的区别
l 编译器处理方式不同
define宏是在预处理阶段展开。
const常量是编译运行阶段使用。
l 类型和安全检查不同
define宏没有类型,不做任何类型检查,仅仅是展开。
const常量有具体的类型,在编译阶段会执行类型检查。
l 存储方式不同
define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
const常量会在内存中分配(可以是堆中也可以是栈中)。
常量为什么存在和存在的意义, 如果不使用常量,直接在程序中填写数字或字符串,将会有什么麻烦?
(1) 程序的可读性(可理解性)变差。程序员自己会忘记那些数字或字符串是什么意
思,用户则更加不知它们从何处来、表示什么。
(2) 在程序的很多地方输入同样的数字或字符串,难保不发生书写错误。
(3) 如果要修改数字或字符串,则会在很多地方改动,既麻烦又容易出错。
一、const修饰普通变量和指针变量
const 修饰变量有两种方式:
const TYPE value;
TYPE const value;
这两种写法本质上是相同的,对于一个非指针的类型TYPE,无论怎么写,都是一个含义,即value值不可变。
但是对于指针类型的TYPE,不同的写法会有不同情况:
(1)指针本身是常量不可变
(char*) const p;
(2)指针所指向的内容是常量不可变
const (char) *p;
(char) const *p;
(3)两者都不可变
const char* const p;
识别const到底是修饰指针还是指针所指的对象,还有一个较为简便的方法,也就是沿着*号划一条线:
如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。
二、const修饰函数参数
用const修饰函数的参数用途非常广泛,也使程序更安全更高效。被声明为const类型的变量在函数体内不容许被改变。
int function(const int val) // val在函数体内不容许改变
int function(const char* val) //val 所指向的内容在函数体内不容许改变
int function(char* const val) // 指针变量val本身是常量 在函数体内的指向不容许改变
int function(const class &val ) // 引用类型在函数体内不许改变
经常在函数传递阐述的时候会使用引用类型是因为,如果该类型是自定的不是系统自带的基本数据类型,如果函数采取的是非引用(值传递),函数会产生临时变量并赋值该变量的至这样影响了函数调用的效率,因此在函数参数传递的过程中经常采用的是传引用。
三、const修饰类对象、对象指针、对象引用
const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
class A
{
public :
int func1();
int func2() const;
};
const A obj;
obj.func1();//error 不能调用非const函数
obj.func2();// ok
const A* obj;
obj->func1();//error
obj->func2();//ok
四、const修饰数据成员
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么,例如:
class A
{
const int size = 100; //错误
int array[size]; //错误,未知的size
}
const数据成员的初始化只能在类的构造函数的初始化列表中进行。
class A
{
A(int size);
const int SIZE;
};
A::A(int size):SIZE(size)
{}
要想建立在整个类中都恒定的常量,可以用类中的枚举常量来实现,例如:
class A
{
…
enum {size1=100, size2 = 200 };
int array1[size1];
int array2[size2];
…
}
枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。
五、const修饰成员函数
const修饰类的成员函数,用const修饰的成员函数不能改变对象的成员变量。一般把const写在成员函数的最后:
class A
{
int func() const;
};
对于const类对象/指针/引用,只能调用类的const成员函数。
六、const修饰成员函数的返回值
1、一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回const对象,或返回const对象的引用,则返回值具有const属性,返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
2、如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针所指的内容)不能被修改,该返回值只能被赋给加const 修饰的同类型指针:
const char * GetString(void);
如下语句将出现编译错误:
char *str=GetString();
正确的用法是:
const char *str=GetString();
3、函数返回值采用“引用传递”的场合不多,这种方式一般只出现在类的赙值函数中,目的是为了实现链式表达。如:
class A
{
…
A &operate= (const A &other); //赋值函数
}
A a,b,c; //a,b,c为A的对象
…
a=b=c; //正常
(a=B)=c; //不正常,但是合法
若赋值函数的返回值加const修饰,那么该返回值的内容不允许修改,上例中a=b=c依然正确。(a=b)=c就不正确了。
还有在重载输入输出流操作符的时候也是这种情况<<, >>。
七 const常量与define宏定义的区别
l 编译器处理方式不同
define宏是在预处理阶段展开。
const常量是编译运行阶段使用。
l 类型和安全检查不同
define宏没有类型,不做任何类型检查,仅仅是展开。
const常量有具体的类型,在编译阶段会执行类型检查。
l 存储方式不同
define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
const常量会在内存中分配(可以是堆中也可以是栈中)。
相关文章推荐
- 您可能不曾注意的C++内置类型选择和使用的注意事项
- C++中的'&'和const的使用注意事项!
- C++学习笔记(二):使用const、static类成员的注意事项
- c++ template怎么使用及注意事项
- 在oracle中字段类型LONG的使用注意事项
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- 【C++注意事项】5 Top-level const , The auto and decltype Type Specifier
- c++之const小结-使用注意
- C++ typename 关键字的使用方法和注意事项
- C++中typename关键字的使用方法和注意事项
- ~c++中的指针使用注意事项
- MySQL索引类型总结和使用技巧以及注意事项
- c++ shared_ptr智能指针使用注意事项
- Unreal Engine 4 C++使用注意事项
- MySQL索引类型总结和使用技巧以及注意事项
- C#中使用FileUpload上传图片到SQL数据库中以image类型存储并使用Image控件显示注意事项
- mysql索引类型-方法-形式-使用时机-不足之处--注意事项
- Brew中使用C++需要注意的事项
- C++使用注意事项