C++中的引用类型
先看一段代码:
int ival = 1024; int &refVal = ival; // ok: refVal refers to ival int &refVal2; // error: a reference must be initialized int &refVal3 = 10; // error: initializer must be an object
引用需要注意的点:
1.引用就是变量的另一个名字,常量都不行;
2.定义引用时必须用与之同类型的变量初始化,初始化后就不能改变他的值了;
3.引用不占用内存。
c++中的const
const用于普通变量
void main(void) { int x = 4; // 定义为变量 const int y = 5; // 定义为常量,跟int const y = 5;一样 x = y; // 给变量x赋值合法 //y = x; // 给常量y赋值出错 }
用const修饰的变量在其作用域内会变成常量,不允许改变其值.
一、const用于指针
这个确实比较蛋疼。const位置不同意义也不同。
1. 指针本身是常量不可变
(char*) const pContent;
char * const pContent;
const (char*) pContent;
这个时候可以看到const修饰的其实是pContent;
2.指针所指向的内容是常量不可变
const (char) *pContent;
const char *pContent;
(char) const *pContent;
char const *pContent;
可以看到const 修饰的是*pContent,修饰的是pContent所指向的变量。
3. 两者都不可变
const char* const pContent;
这个很好理解了。
二、const用于函数参数
被修饰的函数参数在函数体内不能改变其值。
void function(const int Var); //传递过来的参数在函数内不可以改变(无意义,因为Var本身就是形参) void function(const char* Var); //参数指针所指内容为常量不可变 void function(char* const Var); //参数指针本身为常量不可变(也无意义, 因为char* Var也是形参)
三、const修饰类对象/对象指针/对象引用
const修饰类对象/对象指针/对象引用 表示该对象为常量对象,其中的任何成员都不能被修改。
const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
四、const修饰成员变量/成员函数
const修饰类的成员常量,不能被修改,同时它只能在初始化列表中赋值。
class A { … const int nValue; //成员常量不能被修改 … A(int x): nValue(x) {}; //只能在初始化列表中赋值 }
const修饰类的成员函数,表示该成员函数不能修改类中任何非const成员函数。
class A { … void function()const; //常成员函数, 它不改变对象的成员变量. 也不能调用类中任何非const成员函数。 }
五、 const常量与define宏定义的区别
(1) 编译器处理方式不同
define宏是在预处理阶段展开。
const常量是编译运行阶段使用。
(2) 类型和安全检查不同
define宏没有类型,不做任何类型检查,仅仅是展开。
const常量有具体的类型,在编译阶段会执行类型检查。
(3) 存储方式不同
define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
const常量会在内存中分配(可以是堆中也可以是栈中)。
const在c和c++中的区别
C++中的const正常情况下是看成编译期的常量,编译器并不为const分配空间,只是在编译的时候将期值保存在名字表中,并在适当的时候折合在代码中.所以,以下代码:
#include <iostream> using namespace std; int main() { const int a = 1; const int b = 2; int array[ a + b ] = {0}; for (int i = 0; i < sizeof array / sizeof *array; i++) { cout << array << endl; } }
在可以通过编译,并且正常运行.但稍加修改后,放在C编译器中,便会出现错误:
#include <stdio.h> int main() { int i; const int a = 1; const int b = 2; int array[ a + b ] = {0}; for (i = 0; i < sizeof array / sizeof *array; i++) { printf("%d",array); } }
错误消息:
c:\test1\te.c(8): error C2057: 应输入常数表达式
c:\test1\te.c(8): error C2466: 不能分配常数大小为 0 的数组
出现这种情况的原因是:
在C中,const是一个不能被改变的普通变量,既然是变量,就要占用存储空间,所以编译器不知道编译时的值.而且,数组定义时的下标必须为常量.
在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分配存储空间.
C++中定义常量的时候不再采用define,因为define只做简单的宏替换,并不提供类型检查.