C++中的常量定义小结_C 语言

本篇笔记总结自一次代码检视。

一般来说,使用C语言编程时我们都习惯在代码当中使用C当中的宏定义来定义一个数值常量:

#define MY_CONST 7

在C++开发项目时,也会经常存在沿袭C当中常量用法情况。所以,如下的一种写法看起来反倒觉得有些不正宗了:

class MyClass {
  static const int my_const = 7;

  // ...
};

站在编译器的角度,这两种写法都是合法的,但在使用的时候总得二中择一,究竟哪种更合适呢?之前有所耳闻在C++中应该尽可能少的使用C风格的宏定义,这又是为什么呢?

在查找一些资料之后发现,对于减少C当中的宏定义的主要因为下面几个原因:

宏在定义函数的时候极易容易出错,这个时候建议使用inline来替代宏函数。

宏在定义常量的时候在预处理过程中执行文本替换,在编译期间不会生成对应的符号,不利于调试。所以,在C++当中建议使用const或者enum来定义常量。

在C++当中定义一个常量有两种方式,其一是使用static const,另外一种是使用enum。比如:

class MyClass {
  static const int my_const = 7;
  enum {another_const = 7};

  // ...
};

对于这两种方式,又有一些小名堂在里面。对于在类当中使用const来定义常量时,必须要使用static来修饰该常量,并且需要在类定义外部对该常量做出声明。而对于enum来说大可不必如此,所以Bjane Stroustrup在他维护的FAQ当中建议使用enum这种方式来定义常量。

总归来说,在C++当中定义in-class常量可以有多种方法,可行的就有如上提到的三种定义方法。在编写私有项目时当然看个人的喜好,想用哪一种就用哪一种;当作为开发团队的一员的时候遵循团队倡导的代码规范显得更为可取。在这里个人偏向enum这种定义方法,同时我会选择将常量全部大写:)

class MyClass {
  enum {MY_CONST = 7}; 

  // ...
};

我们常在公共头文件中定义一些常量,定义常量方法如下:

方法1

commdef.h(公共头文件):

const int constname = XXX;

在使用该变量的地方加入 #include "commdef.h"

方法2
commdef.h(公共头文件):

extern const int constname;

commdef.cpp文件:

const int constname = XXX;

在使用该变量的地方加入 #include "commdef.h"
由于这两种方式都编译运行没问题,所以程序员很少留意它们的区别。两种方法的比较:

若添加删除常量常量,用方法1更方便,只需在.h文件中修改;若改变常量值,使用方法2的程序因不需要改头文件,则更节省编译时间。

若从内存使用上看,哪种更好?接下来测试看看。

测试程序定义了两个模块,test1和test2,test1.cpp和test2.cpp都引用了commdef.h头文件,使用了全局常量,我们通过查看各个模块的常量地址来确定是否另分配了内存。

环境:Windows + vs2005

// commdef.h文件

#ifndef LX_COMMDEF_H
#define LX_COMMDEF_H
const int MAX_LENGTH = 1024;
extern const int MIN_LENGTH;
#endif

// commdef.cpp文件

#include "commdef.h"
const int MIN_LENGTH = 10;
// test1.cpp文件(注:头文件内容由于简单所以省略掉了)
#include "commdef.h"
#include "test1.h"
#include <iostream>
using namespace std;
void FuncTest1()
{
 cout << "MAX_LENGTH = " << MAX_LENGTH << ", address: " << &MAX_LENGTH << endl;
 cout << "MIN_LENGTH = " << MIN_LENGTH << ", address: " << &MIN_LENGTH << endl;
}

// test2.cpp文件(注:头文件内容由于简单所以省略掉了)

#include "commdef.h"
#include "test1.h"
#include <iostream>
using namespace std;
void FuncTest2()
{
 cout << "MAX_LENGTH = " << MAX_LENGTH << ", address: " << &MAX_LENGTH << endl;
 cout << "MIN_LENGTH = " << MIN_LENGTH << ", address: " << &MIN_LENGTH << endl;
}

输出:

MAX_LENGTH = 1024, address: 00437AE4
MIN_LENGTH = 10, address: 00437B54
MAX_LENGTH = 1024, address: 00437B1C
MIN_LENGTH = 10, address: 00437B54

可见,用方法1定义的常量在多个模块中是分别存储的,用方法2定义的常量是在一处存储的,所以,在存储上,方法2要优于方法1。

特别是当常量多,头文件被引用多的情况下尤其注意,定义不当会带来不必要的内存浪费。

总结:

1. 没有指定类型
#define不涉及为定义的常量做类型检查,为了显式地指定常量类型,需要在常量后加上后缀。比如,对于float类型的常量,在数字后面加上f后缀。

2. 没有指定作用域
#define定义的常量是全局的。

3. 没有访问控制
不能把#define定义的常量标记为公有的,受保护的,或者私有的,它本质上是公有的。
因为宏一旦被定义,它就在其后的编译过程中有效(除非在某处被#undef)。

4. 没有符号
前面的例子中,宏MAX_NUM_SIZE可能会被预处理器从代码中剥离,这样,编译器就无法看见这个名字。这样,程序员在调试时只能看到一些没有任何描述性的常量值。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c++
常量定义
c语言常量的定义、c语言定义常量、c语言字符常量定义、c语言合法常量定义、c语言字符串常量定义,以便于您获取更多的相关知识。

时间: 2024-11-05 22:52:16

C++中的常量定义小结_C 语言的相关文章

Linux c中define的用法小结_C 语言

define的用法只是一种纯粹的替换功能,宏定义的替换是预处理器处理的替换. 一:简单的宏定义用法 格式:#define 标识符 替换内容 替换的内容可以是数字,字符,字符串,特殊字符和空格,后面是什么内容就会替换成什么内容. 例如: #define  N   5 效果等同于 int  array [5]; int  array[N]; 同样效果: #define N = 5 int array[N];    效果等同于 int  array[= 5]; 同样效果: #define N   5;

C++中函数的用法小结_C 语言

函数在C++中的使用,无非2种地方,一处是函数的定义,一处是函数的调用.而函数的定义则非常简单,由三个部分组成:函数的返回类型.函数名和函数的形参表.当然,这里不同的函数定义可以还会稍有不同,比如类的成员函数.内联函数等.这里我们主要讨论函数的调用时需要注意的一些问题. 一.参数传递 我们将函数定义或声明里的参数叫形参,而在调用函数时传入的参数叫实参.那么根据形参类型的不同,有几下形式的参数传递. 1,非引用形参 1)普通的内置类型 普通非引用类型的参数通过复制对应的实参实现形参的初始化.当用实

C++中const用法小结_C 语言

const在C++中使用十分广泛,不同位置使用的意义也不尽相同,所以想写篇文章对其做一个总结. 首先,明确const是"不变"这个基本意义,但是不变不意味着什么都不变,下面将会看到. 1. const与变量 基本原则:const变量(对象)不能被修改 const在变量中的引入和魔数有关,所谓"魔数"指的是突然出现的一个常量值(也叫字面值常量). for(int i = 0; i < 512; i++) { // todo } 上例中,512即为魔数,512突然

C++编程中的数据类型和常量学习教程_C 语言

C++数据类型计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数.浮点数.字符等形式).不同的数据之间往往还存在某些联系(例如由若干个整数组成一个整数数组).数据结构指的是数据的组织形式.例如,数组就是一种数据结构.不同的计算机语言所允许使用的数据结构是不同的.处理同一类问题,如果数据结构不同,算法也会不同.例如,对10个整数排序和对包含10个元素的整型数组排序的算法是不同的. C++的数据包括常量与变量,常量与变量都具有类型.由以上这些数据类型还可以构成更复杂的数据结构.例如利用

全局变量与局部变量在内存中的区别详细解析_C 语言

一.预备知识-程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)- 由编译器自动分配释放,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈. 2.堆区(heap) - 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事,分配方式倒是类似于链表. 3.全局区(静态区)(static)-,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(.data),未初始化的全局变量

C++中inline函数详解_C 语言

本文主要记录了C++中的inline函数,也就是内联函数,主要记录了以下几个问题: 一.C++为什么引入inline函数? 主要目的:用它代替C语言中表达式形式的宏定义来解决程序中函数调用的效率问题. C语言中的宏定义:#define ExpressionName(var1,var2) (var1+var2)*(var1-var2)这种宏定义,它使用预处理器实现,没有了参数压栈.代码生成等一系列得到操作,因此效率很高.但缺点如下: 仅仅是做预处理器符号表中的简单替换,因此不能进行参数有效性的检测

浅谈C语言编程中的布尔bool数据类型_C 语言

我们知道在C++里有专门的bool类型,用来表示真或假.但是在C语言里没有这样的类型(至少我是一直这么认为的),表达式的值0为假,非0为真.所以条件判断语句( if(-).while(-) )非常灵活,甚至一个指针类型都可以是条件表达式. 为了使程序更清晰,我们常常会给出如下的宏定义: typedef int BOOL; #define TRUE 1 #define FALSE 0 这是最常见的写法,能被任何C语言编译器认可. 今天我在一段程序里看见这么一行 #include ,这个陌生的头文件

C语言中数组的一些基本知识小结_C 语言

初始化数组 int ages[3] = {4, 6, 9}; int nums[10] = {1,2}; // 其余的自动初始化为0 int nums[] = {1,2,3,5,6}; // 根据大括号中的元素个数确定数组元素的个数 int nums[5] = {[4] = 3,[1] = 2}; // 指定元素个数,同时给指定元素进行初始化 int nums[3]; nums[0] = 1; nums[1] = 2; nums[2] = 3; // 先定义,后初始化 定义但是未初始化,数组中有

C++中指针的数据类型和运算相关知识小结_C 语言

C++有关指针的数据类型和指针运算的小结 前面已用过一些指针运算(如p++,p+i等),现在把全部的指针运算列出如下. 1) 指针变量加/减 一个整数 例如:p++,p--,p+i,p-i,p+-i,p-=i等. C++规定,一个指针变量加/减一个整数是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数相加或相减.如p+i代表这样的地址计算:p+i*d,d为p所指向的变量单元所占用的字节数.这样才能保证p+i指向p下面的第i个元素. 2) 指针变量赋值 将一个变量地址赋给一个指