c++中的引用类型和const

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只做简单的宏替换,并不提供类型检查.

时间: 2024-11-02 08:35:14

c++中的引用类型和const的相关文章

AIDL文件中 in类型和out类型数据的区别

  最近困惑于aidl文件中 in类型和out类型数据的区别.网上很多解释是:in 输入类型.out输出类型或者in在客户端赋值,out在服务端赋值.但更加具体的就没有了.这里我贴出我写的简单代码,大家尝试一下就会有所了解,希望大家能分享下自己的理解. in表示是输入参数,out表示是输出参数,可以传出某个参数值,inout表示输入输出参数,先传入参数,处理后传出 传值,      是把实参的值赋值给行参      那么对行参的修改,不会影响实参的值           传地址      是传值

eclipse中怎样查看类之间的引用关系

问题描述 我想查看一个项目中的所有类之间的相互引用关系:在A类中查询它引用的所有其他的类可以看开头部分的import就可以知道但是A类要知道整个项目中有哪些类引用了它怎么看(看有些人说是F4,这好像看不到 显示的内容只是A类调用了的哪些方法而已 和outline视图差不多)我想知道eclipse有木有哪个插件可以查看一个类引用哪些类并且哪些类引用它呢? 解决方案 在类名上点击右键,选Reference->Workingspace或者直接快捷键Ctrl+Shift+G解决方案二:Ctrl+T解决方

初学编程语言 C#痴汉 相同类(引用类)中2个实例相互赋值,有什么实际意义或用途? 求路过的痴汉指点一下,谢谢

问题描述 初学编程语言C#痴汉相同类(引用类)中2个实例赋值,有什么实际意义或用途?求路过的痴汉指点一下,谢谢publicclassProgram{staticvoidMain(string[]args){CardC1=newCard();p3.Name="张飞";p3.SN="13553663108";p3.Birthday=DateTime.Now.AddYears(-10);CardC22=newCard();C22=C1;//赋值后,由于是引用类型,因此两个

还是关于java泛型的问题:在静态方法中为什么不能引用类级别的类型参数?

问题描述 不要回答因为泛型类型参数需要声明对象时指定,而静态不需要对象就可以引用什么的.这个根本就不是原因.泛型和运行时系统没有一点关系.我解释一下在静态变量中不能使用类型参数的原因:因为静态变量为所有实例共享,如果可以使用,那么当使用不同的类型参数实例化对象时会导致编译器插入强制类型转换代码错误(1.5版泛型指南上有实例解释).(换句话说泛型的实现机制擦拭法决定了不能再静态变量中使用类型参数).但是这个问题并不影响静态方法中使用类型参数,而且静态方法可以是泛型方法,既然可以使泛型方法,那我引用

Android中重写SimpleAdapter类引用后报空指针异常

问题描述 Android中重写SimpleAdapter类引用后报空指针异常 直接粘代码吧 - - 重写的SimpleAdapter类: public class MySimpleAdapter extends BaseAdapter { private LayoutInflater mInflater; private ArrayList<HashMap<String, Object>> list; private int layoutID; private String fla

理解Java中的引用传递和值传递

关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习和分析一下,着急可以先看最后的结论. >>基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型. 基本类型的变量保存原始值,即它代表的值就是数值本身: 而引用类型的变量保存引用值,"引用值"指向内存空间

ASP进阶:VB中的模块,类,ActiveX与API的使用

active|activex 这几天搞了点c/s结构的程序设计, 由于ASP用得比较熟练,所以VB6.0自然成为我首选的开发工具. 在学习过程中,我结合自己的经验总结下VB中的一些高级应用,并且体会这种应用给我们所带来的好处. 一.模块 (Module) 在VB中,模块会优先执行,其实说白了,模块就象是全局的过程和函数调用.这是初步的提高代码可复用性的途径.我想有经验的ASP(VBSCRIPT,以后都只用VBScript来写Asp程序)程序员都用过<!--#Include file="&q

hadoop中典型Writable类详解

Hadoop将很多Writable类归入org.apache.hadoop.io包中,在这些类中,比较重要的有Java基本类.Text.Writable集合.ObjectWritable等,重点介绍Java基本类和ObjectWritable的实现. 1. Java基本类型的Writable封装 目前Java基本类型对应的Writable封装如下表所示.所有这些Writable类都继承自WritableComparable.也就是说,它们是可比较的.同时,它们都有get()和set()方法,用于

标准C++中的string类的用法总结

相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有没有这样使用起来非常方便的类呢?答案是肯定的.也许有人会说,即使不用MFC框架,也可以想办法使用MFC中的API,具体的操作方法在本文最后给出操作方法.其实,可能很多人很可能会忽略掉标准C++中string类的使用.标准C++中提供的string类得功能也是非常强大的,一般都能满足我们开发项目时使用.现将具体用法的一部分罗列如下,只起一个