C++中const的使用方法

注意这一点

  • const对象默认为文件的局部变量

在全局作用域里定义非const变量时,它在整个程序中都可以访问,我们可以把一个非const变量定义在一个文件中,假设已经做了合适的声明,就可以在另外的文件中使用这个变量:

与其他变量不同,除非特别说明,在全局作用域声明的const变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。通过指定const变量为extern,就可以在整个程序中访问const对象。

注意:非const变量默认为extern。要使const变量能够在其他文件中访问,必须在文件中显式地指定它为extern。

------------- const指针、const引用、const引用形参 --------------------

【1】const修饰指针和引用

1. 术语“const引用”就是“指向const对象的引用”,习惯说成const引用与非const引用。这点与指针不同,指针中“const指针”与“指向const对象的指针”是不同的。

2. 值得注意的是:const引用和指向const对象的指针二者有一个共同点:const引用既可以指向const对象又可以指向非const对象;指向const对象的指针亦是如此.

3. 关于const指针与指向const对象的指针,举一个很简单例子


1

2

3

4

5

6

int
m=1, n=5;

constint
*p1=&m;   //指向const对象的指针:const修饰的是*p1, 即*p1的值是只读的;但是p1这个指针是可以修改的。

int
*
const p2=&n; //const指针:const修饰的是p2, 即p2这个指针是只读的;但是*p2的值是可以修改的。

p1=&n;             //p1的指针修改为变量n的地址,而这个地址就是p2,相当于p1=p2;

*p2=3;             //*p2的值修改为3,当然*p1的值也就是3

printf("%d %d\n",*p1,*p2);

【2】形参为const引用的好处

说到const,就不得不提const引用类型的形参,真正理解了const引用形参的好处,才发现它真是美妙的很

简单总结一下,欢迎补充

a. 当实参的类型比较大时,复制开销很大(形参初始化时),引用会“避免复制”。(这在传递类对象时比较常用)

b. “避免修改实参”,当使用引用时,如果调用者希望只使用实参并不修改实参,则const可以避免使用该引用修改实参

c. 相比非const引用形参,更具实用性:形参可以使用const对象初始化,可使用字面值或右值表达式的实参来初始化

下面各给一示例


1

2

3

4

5

6

7

8

a. voidsearch(constvector<int>
& vec) 避免了实参的复制开销

b. 同a例,可避免对实参做出修改

c. 如下函数,调用时

void
search(string & s);         调用: search(
"hello");// Error 实参为字面值常量

void
search(
const
string & s);   调用: search(
"hello");// OK

再如

void
search(
int & v);            调用: search(v1+v2);  // Error 实参是一个右值,无法给引用赋值(需要左值)

void
search(
const
int
& v);      调用: search(v1+v2);   // OK

---------------const 在类中----------------------------------------

一般来讲,使用const修饰函数,则函数一定是类成员函数。

【1】const对象只能调用const成员函数 非const对象可以调用const成员函数

解释:不能将指向const对象的指针赋值给非const对象指针,而允许将非const对象指针赋值给指向const对象的指针。

为什么这样解释?这源自于调用成员函数时发生的事情:

调用成员函数时会发生的事情:将调用对象与函数绑定,即将成员函数隐含的形参this初始化为调用对象的地址。

因此,const对象传递的实参地址为const class * const this,而非const成员函数被调用时还是使用了class *const this的形参接收,结果就是把指向const对象的指针赋给非const对象的指针,这是不允许的,所以const对象只能调用const成员函数;后者同理,非const对象在调用const成员函数时实质上是将非const对象的指针(实参)赋值给了const对象指针(形参),而这又是可以的,故非const对象可以调用const成员函数。

【2】const成员变量不能被修改,且必须在初始化列表中赋值;

const成员函数不能改变成员变量, 且不能调用非const成员函数(即不可有改变值的企图)

相反,非const成员函数当然可以调用const成员函数

【3】const成员函数的返回值:值类型 & const引用类型  (不可返回非const引用)


1

2

3

4

5

6

7

8

9

10

11

example.

classVec

{

private:

    vector<string> textVec;

public:

    conststring & text_line(size_tlineNum)
const

    {

        returntextVec.at(lineNum-1);

    }

};

如果成员函数为const,则对象调用该常函数传递this时已经变成了const对象,如果函数写成如下形式


1

2

3

4

string & text_line(size_tlineNum)
const

{

    returntextVec.at(lineNum-1);

}

则编译会报错:不能将const string 转化为 string &,因为此时相当于将一个非const引用指向了一个const类型变量。故要返回引用就必须是const引用。

------------返回值类型---

当然还有其他的写法,即让函数返回值为值类型,即


1

2

3

4

string text_line(size_tlineNum)
const

{

    returntextVec.at(lineNum-1);

}

此时实际上是做了一个内存拷贝,因为string是类类型,有人会问,那这样不是相当于一个const对象赋值给非const对象吗?

对于上述函数,实际是调用了string的拷贝构造,而且拷贝构造的参数便是const string类型,这里又涉及到const类型作参数的问题,上面已讲

对于函数的返回值为值类型,无非就两种,一种是普通的内置类型,进行赋值操作;一种是类类型,调用拷贝构造进行内存拷贝。如下:


1

2

3

4

constint
a = 9;

int
b = a;   (
int
&bb = a;
// error)  // 赋值

constset<int> s;

set<int> ss = s;  // 内存拷贝

所以我们要注意:

不可以将const对象指针或引用赋值给非const对象的指针和引用,但是可以将const对象初始化给非const对象;

const与非const在对象层次(not引用或指针层次)上的互相赋值是允许的,可逆的;就像


1

2

3

constint
a = 9;

int
aa = a;

constint
aaa = aa;

-------------------const与重载---------------------------------------

基于const重载的情况有两种,一种是基于函数形参类型是否为const的重载;一种是基于类成员函数是否为const的重载

【1】   基于函数形参类型是否为const的重载

当且仅当形参为引用或指针类型时,形参是否为const才有影响

-----引用类型----

可基于函数的引用形参是指向const对象还是指向非const对象,实现重载,示例如下:


1

2

3

4

5

6

A: voidsearch(Student &);

B: voidsearch(constStudent &);

constStudent a;

Student b;

search(a); 
// 调用B

search(b); 
// 调用A

注:根据上面讲的我们知道,如果形参是普通引用,则不能将const对象传递给该形参。

如果传递的是非const对象,按上面提到的,这两种函数都是可行的,因为非const对象既可用于初始化const引用,也可初始化非const引用。那么没有二义性么?

这就是编译器在调用函数时遵循的原则首先是“精确匹配”,我们知道,将const引用初始化为非const对象需要隐式转换的,所以不符合精确匹配,故调用A。

-----指针类型----

基于指针形参的const重载与引用是一样的。只是有一个问题要注意:

上面术语说到const引用就是指向const对象的引用,指针则区别于const指针和指向const对象的指针。

所以要注意:不能基于指针本身是否为const来重载函数


1

2

3

4

void
search(
int * ptr);

void
search(
int *
const ptr);

// 这不能实现重载,指针本身是否const并不会带来区别

// 在函数调用时,形参都复制了指针的值

【2】   基于类成员函数是否为const的重载

在类中,基于成员函数是否为const,可重载一个成员函数,如下


1

2

3

4

5

6

7

8

9

10

11

12

13

14

classVec

{

private:

    vector<string> textVec;

public:

    conststring & text_line(size_tlineNum)
const

    {

        returntextVec.at(lineNum-1);

    }

    string & text_line(size_tlineNum)

    {

        returntextVec.at(lineNum-1);

    }

};

C++中const的使用方法

时间: 2024-10-29 05:11:49

C++中const的使用方法的相关文章

C++中const限定符的应用

const限定符用于限定变量或对象的值.const对象一旦创建其值不能再改变.在C++中,const与引用和指针相结合,有多种用法.下面将结合<C++ Primer>第五版的内容做一个较详细的介绍. 1.const对象初始化 const对象必须初始化,初始化可以是任意复杂的表达式,如: const int i=get_size(); const int j=42; 2.文件间共享const对象 当以编译时初始化的方式定义一个const对象时,编译器将在编译过程中把用到该变量的地方都替换成对应的

c++中const关键字全面总结

一.const作用 1.const定义常量 注意:const只对它左边的东西起作用,唯一的例外就是const本身就是最左边的修饰符,那么它才会对右边的东西起作用. (1)const修饰变量,以下两种定义形式在本质上是一样的.它的含义是:const修饰的类型为TYPE的变量value是不可变的. TYPE const ValueName = value; const TYPE ValueName = value; (2)将const改为外部连接,作用于扩大至全局,编译时会分配内存,并且可以不进行初

C/C++中容器vector使用方法&lt;第二弹&gt;

此文总结常用vector操作,是前一篇的续作!只有代码,详细请看代码中的注释.出于反爬虫的目的,你不是在http://blog.csdn.net/zhanh1218上看到的,肯定不是最新最全的. /********************************************************************* * file_name: vector_test.cpp * * Created on: 2014年6月28日 下午3:34:23 * Author: The_T

linux中select的使用方法

fd_set是一组文件描述符(fd,file descriptor)的集合,它用一位来表示一个fd. 系统提供了4个宏对描述符集进行操作: #include <sys/select.h>#include <sys/time.h> //设置文件描述符集fdset中对应于文件描述符fd的位(设置为1)void FD_SET(int fd, fd_set *fdset); //清除文件描述符集fdset中对应于文件描述符fd的位(设置为0)void FD_CLR(int fd, fd_s

C++中const用法总结

1. const修饰普通变量和指针const修饰变量,一般有两种写法:const TYPE value;TYPE const value;这两种写法在本质上是一样的.它的含义是:const修饰的类型为TYPE的变量value是不可变的.对于一个非指针的类型TYPE,无论怎么写,都是一个含义,即value只不可变.例如:const int nValue:         //nValue是constint const nValue:    // nValue是const但是对于指针类型的TYPE,

结合示例说明C++中const和指针结合时怎么理解

在之前随笔<C++中const使用要点(一)>中简单叙述了const int*.int* const和const int* const的区别,记住三句话就能在实际运用时用对,但是看书时发现了指针常量.常量指针这些名词,发现明白这些概念对阅读文章时还是比较重要的. 关键:const和指针结合时代码从右往左看 1.常量指针(const pointer) 概念:常量是形容词,也就是说常量指针是一个指针,用const修饰的指针. 按照代码从右往左(概念名词从左往右)的阅读顺序,不妨试着写一下. Ste

(转) C/C++中const关键字详解

文章转自  http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html 为什么使用const?采用符号常量写出的代码更容易维护:指针常常是边读边移动,而不是边写边移动:许多函数参数是只读不写的.const最常见用途是作为数组的界和switch分情况标号(也可以用枚举符代替),分类如下: 常变量:  const 类型说明符 变量名 常引用:  const 类型说明符 &引用名 常对象:  类名 const 对象名 常成员函

C# 中的可变参数方法(VarArgs)

首先需要明确一点:这里提到的可变参数方法,指的是具有 CallingConventions.VarArgs 调用约定的方法,而不是包含 params 参数的方法.可以通过MethodBase.CallingConvention 属性来获取某个方法的调用约定. 举个常见的例子来说,C 语言的 printf 方法大多数人应该都知道,它的作用是向标准输出流(stdout)写入格式化字符串,printf 的方法签名是: int printf(const char * format, ...); 方法签名

JNI中C调用Java方法

背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT void JNICALL Java_cn_itcast_ndkcallback_DataProvider_callmethod1 (JNIEnv * env, jobject obj){ //在c代码里面调用java代码里面的方法 // java 反射 //1 . 找到java代码的 class文件