1.1.1. 定义普通常量

使用#define来定义常量也是常用方法,但const也可以用来定义常量,在[Effective C++]中建议使用const代替#define来定义常量,因为const定义的常量具有类型信息,而宏没有,所以使用const定义的常量在进行赋值操作时编译器会进行更严格的类型检查,是类型安全的。

const double PI = 3.1414926;

const int POOL_SIZE = 20;

定义常量有三种方法:宏、const、enum,其中宏应该尽量避免,而const与enum也各有优缺点,最大的区别就是enum只能用于定义整数,而不能定义浮点数;而对于定义逻辑关系较近的一组整数时比较适合使用enum,也可以考虑使用类代替enum(参见[??])。

常量必须在定义时进行初始化,之后便不能再赋值。说它不能被赋值并不是说常量的值是绝对不会改变的,只是说不能直接赋值,但可以通过指针及强制类型转换、const_cast是可以改变常量的值的。

#include

using namespace std;

int main( void )

{

const int ci = 5;

const int* cpci = &ci;

int *pci = (int*)&ci;

cout<

return 0;

}

输出结果:

cpci = 002DFAC8, pci = 002DFAC8

ci=5, *cpci=1, *pci=1

ci=5, *cpci=2, *pci=2

ci != *cpci

之所以使用ci直接输出变量的值时显示其值始终没有改变,但通过指针间接显示出来的值是改变了,而且输出结果的最后一行很奇怪,ci的值与*cpci的值居然不相等,只因为编译器在编译时进行了优化,将代码中的ci直接替换成了5,与宏替换是相同的效果,而指针的值则是实际内存中的值。

所以,千万不要试图使用指针强行改变const变量的值,否则程序可能表现出错误的行为,而且查找起来这种错误非常困难。在gcc 4.3.4和visual C++ 2010中均默认打开了对常量的优化选项,目前还没找到关闭该优化的命令行选项,一定不要自作聪明去改const变量的值。

1.1.2. 修饰指针

把const与指针放到一起,很多人便会想到一个绕口令“指针常量与常量指针。“指针常量”即一个指针变量,该变量不能被赋值,而指针指向的内存单元的内容是可以改变的;“常量指针”即一个指向常量的指针,指针变量本身可以赋值,而指针指向的内存单元的内容是不可以被重新赋值的。

char a = 'A', b = 'B';

const char* ptoc = &a; // 常量指针

*ptoc = 'C'; // 改变指针指向内存单元的内容,不可以

ptoc = &b; // 改变指针的值,可以

char* const cp = &a; // 指针常量

cp = &b; // 改变指针的值,不可以

*cp = 'D'; // 改变指针指向内存单元的内容,可以

const char* const cptoc = &a; // 指向常量的指针常量

*cptoc = 'E'; // 不可以

cptoc = &b; // 不可以

const是修饰类型还是修饰指针,要看const的位置,放在*前就是修饰数据类型,放到*后就是修饰指针,const char和char const是一样的。

建议:在不打算修改数据内容的时候都将指针定义成常量指针,不打算指针本身被修改的场合都定义成指针常量。尽可能地多用const,用错了没关系,编译器会提示你的,只要能够编译通过,就不会因为用错const而导致程序逻辑错误,应该说const负作用极小。

1.1.3. 修饰类成员常量

当使用const修饰类成员变量时便定义了常数据成员,它的使用与使用类外定义的常量本质上并没有什么区别,在这里只想指出一点:有网友提到const数据成员只能被const修饰的函数使用这是没有根据的,是错误的。

1.1.4. 修饰类成员函数

const修饰成员函数语法:

class Socket

{

public:

typedef unsigned short socket_port_t;

socket_port_t LocalPort( void ) const

{

++readCount;

return _port;

}

private:

socket_port_t _port;

mutable int _readCount;

};

使用const修饰的成员函数不能修改类的成员变量,如成员_port,而且只能调用成员类对象const函数,但有个例外,就是mutable修饰的成员变量可以在const修饰的成员函数中被修改,如_readCount。

另外,const只能修饰非静态函数。

建议:将所有不改变对象状态的函数都使用const修饰符标识,以提高程序的可读性。其实,头文件就是最好的类接口的说明文档,越多的提供信息就能使程序的可读性越好,越利于维护。看到成员函数的const修饰符,读者便立即明白该函数不会改变程序的状态,这也有利于当程序状态出现异常时的问题定位。

1.1.5. 修饰类对象、对象引用或对象指针(常量指针)

当const修饰自定义的类对象时,与修饰C++内置类型的变量的思想是一致的,但稍有不同,除了不能被赋值外,还不能调用没有使用const修饰的非静态成员函数。当const修饰类对象引用、指针时限制是一样的,因为引用本身与直接使用该变量实质上没有区别,而使用指针只是将.操作符改为了->本质上还是一样的

const std::string hello = “Hello from Noock Tian;

std::cout<

hello = "Hi"; // 不可以赋值

hello.push_back("!"); // 不可以

1.1.6. 修饰函数参数

const修饰函数的例子是很常见了,表示函数的参数在函数体内不会被意外修改,一般用于修饰输入参数,例如标准库中的字符串连接函数。str1是输出参数,其内容会被修改,而str2为输入参数,其内容不会修改。

char* strcat(char* str1, const char* str2);

实际上在说到const用法一开始就提到,const只是一种声明,但并不能保证,例如strcat函数虽然声明了str2为const char*型,但并不能保证内部绝对不会修改str2的内容。但const从语言本身提供了一种编写自描述性代码的方法,只要使用函数与实现函数的双方都达成一致的约定,按照契约编程,我们就可以认为const修饰的类型在函数体内不会被修改,这与const修饰类成员函数一样,可以提高软件的可读性。

1.1.7. 修饰函数返回值

const可以用于修饰任何类型,只要返回值类型不是void,const就可以用来修饰返回值的类型。但实际上const用于修饰非引用的返回值类型是没有意义的,因为返回值一般都会被赋值给另一个变量,此时用于传递返回值的对象已经被销毁,修饰返回值类型的const的作用也就终结了。

当返回值是引用类型时,如果该引用的值不希望被修改是可以声明为常引用的,例如:

class Socket

{

public:

const string& IP( void ) const{ return _ip; }

private:

string _ip;

};

Socket sock;

string& ip = sock.IP(); // 不可以

const string& ip2 = sock.IP(); // 可以

string ip3 = sock.IP(); // Socket::_ip被复制,可以

此处,为了减少构造临时变量,将IP函数返回值定义为引用类型以提高程序运行效率,但为了保护内部状态不会被客户端代码意外,返回值使用const修饰为常引用。但是,如果对于软件安全性较高的场合,最好不要定义为引用,因为恶意的客户端代码是有可能修改Socket::_ip的值的。

在C++中赋值运算符反默认返回值都是引用,但笔者认为定义为常引用更为合适,例如:

int main( void )

{

int a = 1,b = 2,c = 3,d = 4;

((a=b)=c)=d;

cout<

return 0;

}

输出结果:

a=4, b=2, c=3, d=4

显然,在实际工程中谁也不会写出这样的代码,这段代码却是合法的,无疑这给程序员多了一种出错的可能,如果把赋值运算符的返回值定义为常引用,则会减少程序员出错的机会,例如[??]:

class Object

{

public:

const Object& operator=(const Object& a) { return *this; }

};

int main( void )

{

Object a, b, c, d;

a = b = c = d; // 可以

((a=b)=c)=d; // 不可以

return 0;

}

在gcc 编译时则会出现错误提示:

error: passing ‘const Object’ as ‘this’ argument of ‘const Object& Object::operator=(const Object&)’ discards qualifiers.

当然,不同的编译器可能错误提示不同。

C语言返回值是const类型,C++中const用法总结相关推荐

  1. Swift2.0语言教程之函数的返回值与函数类型

    Swift2.0语言教程之函数的返回值与函数类型 Swift2.0中函数的返回值 根据是否具有返回值,函数可以分为无返回值函数和有返回值函数.以下将会对这两种函数类型进行讲解. Swift2.0中具有 ...

  2. 编写一个C程序,实现以下功能:编写一个常规的函数和一个递归函数,两个函数均能将输入的一个字符串以按反序形式的字符串作为返回值。在main函数中输入一行字符串,分别调用两个函数,输出反序后的字符串。

    题目要求: 编写一个C程序,实现以下功能:编写一个常规的函数和一个递归函数,两个函数均能将输入的一个字符串以按反序形式的字符串作为返回值.在main函数中输入一行字符串,分别调用两个函数,输出反序后的 ...

  3. python中的返回值是什么意思_python中函数的返回值是什么

    函数返回值简介 1.简单介绍print和return的区别,print仅仅是打印在控制台,而return则是将return后面的部分作为返回值:作为函数的输出,可以用变量接走,继续使用该返回值做其它事 ...

  4. bind函数 c语言 返回值,多重返回值的阵营九宫格

    通常在糊业务代码的时候,不管是函数.方法,还是宏,都只会有一个返回值.比如在C语言用于检查一个字符是否为阿拉伯数字的isdigit函数就只会返回是(1)或否(0)#include #include i ...

  5. 函数返回值为指针类型的总结

    参考博客:https://blog.csdn.net/zxccaoya/article/details/53468500 char*GetString(void) {char p[]= "h ...

  6. Python 函数参数有冒号 声明后有- 箭头 返回值注释 参数类型注释

    在python3.7 环境下 函数声明时能在参数后加冒号,如图: 1 def f(ham: str, eggs: str = 'eggs') -> str : 2 print("Ann ...

  7. python冒号声明类型_Python 函数参数有冒号 声明后有- 箭头 返回值注释 参数类型注释...

    在python3.7 环境下 函数声明时能在参数后加冒号,如图: 1 def f(ham: str, eggs: str = 'eggs') -> str : 2 print("Ann ...

  8. c语言返回值作用,c语言的返回值是什么意思啊?

    c语言的返回值是什么意思啊? 关注:204  答案:6  手机版 解决时间 2021-01-17 03:28 提问者怪咖 2021-01-16 11:08 例如下题 求三个整型参数的最大值函数 int ...

  9. java 返回值判断_在Java中判断方法重载的条件除了参数外,还可以通过返回值类型判断。_学小易找答案...

    [单选题]若int x;且有下面的程序片断,则输出结果是() . for (x=3; x<6; x++) { printf((x%2) ? "##%d" : "** ...

最新文章

  1. php根据不同的条件替换一段html代码中的不同的img标签
  2. Hologres基于TPCH的性能测试介绍
  3. UIApplication,UIWindow,UIViewController,UIView(layer)
  4. 【数字信号处理】——Python频谱绘制
  5. 数据库事务隔离级别-- 脏读、幻读、不可重复读(清晰解释)
  6. 热乎的宇宙条总部面经,已拿offer,速来围观
  7. 如何用 30 天入门年薪 30 万的技术领域?
  8. 分享一套帮助你优化开发web应用的jQuery插件集 - Vanity Toolset
  9. 第29课 - 排序课后练习
  10. OAuth 2和JWT - 如何设计安全的API?
  11. 用reloadRowsAtIndexPaths刷新单个cell 跳动问题
  12. windows下 PHP 安装
  13. 圈粉无数!被称为B站“新垣结衣”的UP主,如何收获Z世代年轻人的喜爱?
  14. python爬取通过百度图片搜出来的所有图片
  15. 常用照片尺寸与像素对照表
  16. 使用gdb调试出现 No debugging symbols found in a.out
  17. MAC主机eclipse连接parallels内win7虚拟机oracle
  18. 不积小流,无以成江海;不积跬步,无以至千里
  19. 著作权法_信息网络传播权保护条例_最高人民法院关于审理侵害信息网络传播权民事纠纷案件适用法律若干问题的规定
  20. 问题解决:#include errors detected. Please update your includePath.

热门文章

  1. 提示工程师是什么工作?
  2. 用MATLAB设计一个超简单的变声GUI界面
  3. 数三角形 (组合数学+分类讨论)
  4. Bootstrap组件福利篇:十二款好用的组件推荐
  5. 红米note8pro支不支持html,红米note8pro隐藏功能
  6. 浅尝不辄止系列之试试腾讯云的 TUIRoom(下)
  7. JAVA-IO流笔记整理----(2)字节流输入输出
  8. 国民家轿的涅槃,全新奔腾B70来袭!
  9. 大咖面对面 | Reva:NFT 发展路上的“无限回廊”
  10. 老大老二打架,怎么倒霉的总是老三?快手抖音PK陌陌暴跌!