C++语言中const关键字用法总结

时间:2024.4.13

C++语言中const关键字用法总结

一、const是什么

在 C/C++ 语言中,const关键字是一种修饰符。所谓“修饰符”,就是在编译器进行编译的过程中,给编译器一些“要求”或“提示”,但修饰符本身,并不产生任何实 际代码。就 const 修饰符而言,它用来告诉编译器,被修饰的这些东西,具有“只读”的特点。在编译的过程中,一旦我们的代码试图去改变这些东西,编译器就应该给出错误提示。

所以,const修饰符的作用主要是利用编译器帮助我们检查自己代码的正确性。我们使用const在源码中标示出“不应该改变”的地 方,然后利用编译器,帮助我们检查这些地方是否真的没有被改变过。如果我们不小心去修改了这些地方,编译器就会报错,从而帮助我们纠正错误。使用 const和不使用const,对于最终编译产生的代码并没有影响。

虽然const对于最终代码没有影响,但是尽可能使用const,将帮助我们避免很多错误,提高程序正确率。

二、const可以修饰哪些对象

在上面已经提到过了,const是一种修饰符,那它可以作为哪些对象的修饰符呢?下面列举了一些C/C++中用到const的地方。

1,const变量

2,const指针

3,const引用

4,const类

5,类的const成员变量

6,类的const成员函数

7,const修饰函数的形参与返回值

下面我们分别讨论上面几种情况下,const的用法。

三、const与变量

当一个变量被const修饰后,具有以下几个特点:

1)该变量只能读取不能修改。(编译器进行检查)

2)定义时必须初始化。

3)C++中喜欢用const来定义常量,取代原来C风格的预编译指令define。 1 const int var; // Error:常量 变量"var"需要初始化设定项

2 const int var1 = 42;

3 var1 = 43; // Error:表达式必须是可以修改的左值

上面代码中第一行和第三行都有错误,注释便是编译器给出的错误提示。

另外注意,在使用const变量作为数组的下标时,变量的值一定要是一个常量表达式(在编译阶段就能计算得到结果)。

1 const int sz = 42;

2 int iAr[sz];

3 const int sz1 = size(); // size()必须是一个返回常量的函数

4 int iAr1[sz1];

5

6 int var = 42;

7 const int sz2 = var;

8 int iAr2[sz2]; // error:sz2只有运行时才知道值

四、const与引用

我们知道,引用必须在定义的时候赋值,这样就会所引用的变量绑定在一起并作为它的一个别名,在程序中的其他地方,是不能让引用再与其他对象绑定。这个特性,让引用看起来就像是const对象一样,一旦定义后将不能更改。所以并不存在const的引用。

但是我们却可以引用一个const的对象(变量),我们称之为对常量的引用,与普通的引用不同的时,对常量的引用不能被用作修改它所绑定的对象。

1 const int ci = 1024;

2 const int &r1 = ci;

3 r1 = 42; // Error:r1是对常量的引用

4 int & r2 = ci; //Error:不能将一个非常量引用指向一个常量的对象

我们知道,引用的类型必须与其所引用对象的类型一致,如下面的代码:

double dval = 3.14;

int& ri = dval; // Error:无法用double类型的值初始化int&类型的引用(非常量限定) 上述代码为何不行?

此处ri引用了一个int型的整数。对于ri的操作数应该是整数运算,但是dval却是一个双精度的浮点数而非整数。因此为了确保让ri绑定一个整数,编译器把上述代码变成了如下形式:

double dval = 3.14;

int temp = dval;

int& ri = temp;

其中temp是一个临时变量,而ri绑定了一个临时量,所以当ri改变时,并没有改变davl的值,所以这种引用是无效的。

也许你注意到了,当我们把double变量绑定在一个int&类型上时,编译器提示后有个括号:非常量限定。这说明如果是一个常量的引用,则有可能是通过的,显然下面的代码就没有任何问题:

double dval = 3.14;

const int& ri = dval;

因为在这里,ri是一个常量引用,我们并不想通过ri改变dval的值,只要能读到dval对应的int型的值就行。

五、const与指针

我们知道,指针与引用不同,指针本身是一个对象,所以存在常量指针,这种指针在

定义并初始化后,便不能再指向其他变量。用来修饰这种常量指针的const,我们称之为"顶层const"。

与顶层指针对应的是底层指针,这种指针指向一个const修改的对象,这一点上就有点像是常量的引用。

对于指向常量的指针或引用,都有以下规则:

1)可以将一个非const对象的地址赋给一个指向const对象的指针

2)可以将一个非const对象的地址赋给一个指向非const对象的指针

3)可以将一个const对象的地址赋给一个指向const对象的指针

4)不可以将一个const对象的地址赋给一个指向const对象的指针。

1 int var;

2 const int ci = 42;

3

4 int *p1 =& var;

5 int *p2 = &ci; // Error,const int* 不能用于初始化int*

6 const int *p3 = &var; //ok

7 const int *p4 = &ci; // ok

还有一种指向const对象的const指针,这种指针首先表明,本身是一个const指针,一旦初始化后不能指向其他对象;其次,它本身所指向的对象也是一个常量,即不能通过指针修改对象的值。

const int var = 42;

const int* const p = &var;

这里再强调一点,const只是给编译器看的,我们可以很轻松的骗过编译器,并看看编译器都做了什么:

1 const int var = 42;

2 int* p = (int*)&var;

3 *p = 20;

4 cout << var << endl; //42

5 cout << *p << endl; //20

我们在代码的第2行,用一个类型转换强制的,把一个非const指针指向了一个const对象。

但是后面我们通过这个指针来修改这个值,却没有生效,原因呢?

那是因为编译器在编译阶段发现var是一个常量,所以在编译目标代码时已经将var的地方都用42进行了替换。

六、const与类

其实类定义的对象,与普通的变量是一样的,用const修饰时,说明这个类是一个常量类对象,这个对象有下面2个特点:

1)不能改变其成员变量(非mutalbe成员)

2)不能调用其非const成员函数

1 class AClass{

2 public:

3 int m_var;

4 mutable int m_mutable_var;

5 void setVar(int var){ m_var = var; }

6 void printVar(){ cout << m_var; }

7 void printVar_const()const { cout << m_var; }

8 };

9

10 const AClass ac;

11 ac.m_var = 20; // Error:ac是一个const类,不能修改成员变量

12 ac.m_mutable_var = 42; // ok 可以修改mutable修饰的变量

13 ac.setVar(20); // Error: ac不能调用非const成员函数,而且这个成员函数还修改了成员变量的值

14 ac.printVar();// Error:ac不能调用非const成员函数

15 ac.printVar_const(); // ok

七、const与类的成员

1,const成员变量

const 成员变量指的是类中的成员变量为只读,不能够被修改(包括在类外部和类内部)。

1)const 成员变量必须在类的构造函数初始化表达式中被初始化,即使在构造函数体内也不可以。

2)静态 const 成员变量需要在类外部单独定义并初始化(可定义在头文件)

1 class constTestClass

2 {

3 public:

4 const int var;

5 static const int sci;

6 public:

7 constTestClass() :var(42){} // const成员变量必须在类的构造函数初始化列表中初始化

8 };

9 const int constTestClass::sci = 42; // static const成员变量需要在类外单独进行定义和初始化

类对象的实例化过程可以理解为包含以下步骤: 首先,开辟整个类对象的内存空间。之后,根据类成员情况,分配各个成员变量的内存空间,并通过构造函数的初始化列表进行初始化。最后,执行构造函数中的代 码。由于 const 成员变量必须在定义(分配内存空间)时,就进行初始化。所以需要在够在函数的初始化列表中初始化。const成员在初始化之后,其值就不允许改变了,即便在构造内部也是不允许的。

静态成员变量并不属于某个类对象,而是整个类共有的。静态成员变量可以不依附于某个实例化后的类对象进行访问。那么,静态成员变量的值,应该在任何实例化操作之前,就能够进行改变(否则,只有实例化至少一个对象,才能访问静态成员)。所以,静态成员变量不能够由构造函数进行内存分配,而应该在类外部单独定义,在实例化任何对象之前,就开辟好空间。又由于 const 成员变量 必须初始化,所以静态成员变量必须在定义的时候就初始化。

2,const成员函数

const成员函数指的是,此函数不应该修改任何成员变量。

1)传给const成员函数的this指针,是指向 const 对象 的 const 指针。

2)const成员函数,不能够修改任何成员变量,除非成员变量被 mutable 修饰符修饰。 1 class constTestClass

2 {

3 public:

4 int var;

5 const int ci;

6 mutable int mci;

7 public:

8 void setVar(int i);

9 void setMci(int i)const;

10 };

11 void constTestClass::setVar(int i)

12 {

13 var = i; // ok

14 mci = i; // ok

15 ci = i; // Error:ci是一个const对象不能修改

16 }

17 void constTestClass::setMci(int i)const

18 {

19 var = i; // ok

20 mci = i; // ok mutable成员变量可以被const成员函数修改

21 ci = i; // Error

22 }

在成员函数调用的过程中,都有一个 this 指针被当做参数隐性地传递给成员函数(可能通过栈,也可能通过CPU寄存器)。这个this指针,指向调用这个函数的对象(这样,成员函数才能找到成员变量的地址,从而对其进行操作)。这个this指针,是个 const指针,不能修改其指向(你不希望这个对象的函数,修改了那个对象的成员变量,对吧?)。

传递给const成员函数的this指针,指向一个const对象。也就是说,在const成员函数内部,这个this指针是一个指向const对象的const指针。

mutable 修饰符使得const函数的行为有了一些灵活性。相当于提醒编译器,这个成员变量比较特殊,就不要进行任何只读检查了。

为什么 const 对象只能够调用const成员函数呢?,其实是这样的。由于对象本身通过 const 修饰,那么指向这个对象的指针也就是指向const对象的const指针了。换句话说,指向这个对象的this指针就是指向const对象的const指针。一般成员函数要求的this指针为:指向对象的const指针。所以此处发生了参数不匹配,无法进行调用。而 const 成员函数要求的this指针,恰恰是 指向const对象的const指针。所以依然能够调用。

八、const与函数

将函数的形参用const修饰是希望实参在函数内部不被修改,而一般函数接口可能会遇到以下三种情况:

1,const对象

2,指向const对象的指针

3,绑定const对象的引用

4,返回值是一个const对象

首先,我们看const对象的形参,这种接口用const修饰实际上没有任何意义,因为实参在传递给实参时是传递了一份副本,原实参是不会变化的。

1 int main(void)

2 {

3 int var = 42;

4 fun(var);

5 cout << var << endl; // print 42

6 return 0;

7 }

8 void fun( int i)

9 {

10 i = 10;

11 }

通过上面代码可以看出,实参如果只能过值进行传递,函数接口不用const修改,也不会令实参的值改变。

而通过指针或引用传递给函数时,函数就可以通过形参来改变实参的值,这里如果需要对实参进行保护,则需要在函数接口声明形参为指向const类型的指针或引用。

1 void fun( const int* p)

2 {

3 *p = 42; // error

4 int var = 10;

5 p = &var; // 可以改变p本身的值

6 }

7 void fun(const int& p)

8 {

9 p = 42; // error,p是一个指向const对象的引用

10 }

有的时候,我们需要函数的返回值是一个const对象,比如我们考虑一个有理数据类,我们给类定义了一个*的重载。

1 class Rational{

2 // ....

3 };

4 const Rational operator* (const Rational& lhs, const Rational& rhs);

5 Rational a, b, c;

6 a*b = c; // Error,因为左端为一个const对象

如果上面代码中重载操作符返回对象不是const类型,则a*b=c这个式子就成立,实际上这与我们的内置类型的算术运算原则违背了,而我们希望我们设计的类的操作意义要像内置内类一样。


第二篇:C语言--const的用法


C语言--const的用法

1、什么是const?
常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。(当然,我们可以偷梁换柱进行更新:)

2、为什么引入const?
  const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。

3、cons有什么主要的作用?
(1)可以定义const常量,具有不可变性。
例如:
const int Max="100";
int Array[Max];
(2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。
例如:
void f(const int i) { .........}
编译器就会知道i是一个常量,不允许修改;
(3)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。
同宏定义一样,可以做到不变则已,一变都变!如(1)中,如果想修改Max的内容,只需要:const int Max="you" want;即可!
(4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。
还是上面的例子,如果在函数体内修改了i,编译器就会报错;
例如:
void f(const int i) { i="10";//error! }
(5) 为函数重载提供了一个参考。
class A
{
......
void f(int i) {......} file://一个函数
void f(int i) const {......} file://上一个函数的重载
......
};
(6) 可以节省空间,避免不必要的内存分配。
例如:
#define PI 3.14159 file://常量宏
const doulbe Pi="3".14159; file://此时并未将Pi放入ROM中
......
double i="Pi"; file://此时为Pi分配内存,以后不再分配!
double I="PI"; file://编译期间进行宏替换,分配内存
double j="Pi"; file://没有内存分配
double J="PI"; file://再进行宏替换,又一次分配内存!
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。
(7) 提高了效率。
编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

3、如何使用const?
(1)修饰一般常量
   一般常量是指简单类型的常量。这种常量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后。
例如:
int const x="2";  或  const int x="2";
(2)修饰常数组
   定义或说明一个常数组可采用如下格式:
   int const a[5]={1, 2, 3, 4, 5}; 
const int a[5]={1, 2, 3, 4, 5};
(3)修饰常对象
 常对象是指对象常量,定义格式如下:
class A;
   const A a;
A const a;
   定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面。 
(4)修饰常指针
const int *A; file://const修饰指向的对象,A可变,A指向的对象不可变
int const *A;   file://const修饰指向的对象,A可变,A指向的对象不可变
int *const A;   file://const修饰指针A, A不可变,A指向的对象可变
const int *const A; file://指针A和A指向的对象都不可变
(5)修饰常引用
 使用const修饰符也可以说明引用,被说明的引用为常引用,该引用所引用的对象不能被更新。其定义格式如下:
   const double & v;
  (6)修饰函数的常参数
const修饰符也可以修饰函数的传递参数,格式如下:
void Fun(const int Var);
告诉编译器Var在函数体中的无法改变,从而防止了使用者的一些无意的或错误的修改。
(7)修饰函数的返回值:
const修饰符也可以修饰函数的返回值,是返回值不可被改变,格式如下:
const int Fun1();
const MyClass Fun2();
(8)修饰类的成员函数:
const修饰符也可以修饰类的成员函数,格式如下:
class ClassName
{
public:
   int Fun() const;
  .....
};
这样,在调用函数Fun时就不能修改类里面的数据
(9)在另一连接文件中引用const常量
extern const int i; file://正确的引用
extern const int j="10"; file://错误!常量不可以被再次赋值
另外,还要注意,常量必须初始化!
例如:
const int i="5";

4、几点值得讨论的地方:
(1)const究竟意味着什么?
说了这么多,你认为const意味着什么?一种修饰符?接口抽象?一种新类型?
也许都是,在Stroustup最初引入这个关键字时,只是为对象放入ROM做出了一种可能,对于const对象,C++既允许对其进行静态初始化,也允许对他进行动态初始化。理想的const对象应该在其构造函数完成之前都是可写的,在析够函数执行开始后也都是可写的,换句话说,const对象具有从构造函数完成到析够函数执行之前的不变性,如果违反了这条规则,结果都是未定义的!虽然我们把const放入ROM中,但这并不能够保证const的任何形式的堕落,我们后面会给出具体的办法。无论const对象被放入ROM中,还是通过存储保护机制加以保护,都只能保证,对于用户而言这个对象没有改变。换句话说,废料收集器(我们以后会详细讨论,这就一笔带过)或数据库系统对一个const的修改怎没有任何问题。
(2)位元const V.S. 抽象const?
对于关键字const的解释有好几种方式,最常见的就是位元const 和 抽象const。下面我们看一个例子:
class A
{
public:
......
A f(const A& a);
......
};
如果采用抽象const进行解释,那就是f函数不会去改变所引用对象的抽象值,如果采用位元const进行解释,那就成了f函数不会去改变所引用对象的任何位元。
我们可以看到位元解释正是c++对const问题的定义,const成员函数不被允许修改它所在对象的任何一个数据成员。
为什么这样呢?因为使用位元const有2个好处:
最大的好处是可以很容易地检测到违反位元const规定的事件:编译器只用去寻找有没有对数据成员的赋值就可以了。另外,如果我们采用了位元const,那么,对于一些比较简单的const对象,我们就可以把它安全的放入ROM中,对于一些程序而言,这无疑是一个很重要的优化方式。(关于优化处理,我们到时候专门进行讨论)
当然,位元const也有缺点,要不然,抽象const也就没有产生的必要了。
首先,位元const的抽象性比抽象const的级别更低!实际上,大家都知道,一个库接口的抽象性级别越低,使用这个库就越困难。
其次,使用位元const的库接口会暴露库的一些实现细节,而这往往会带来一些负面效应。所以,在库接口和程序实现细节上,我们都应该采用抽象const。
有时,我们可能希望对const做出一些其它的解释,那么,就要注意了,目前,大多数对const的解释都是类型不安全的,这里我们就不举例子了,你可以自己考虑一下,总之,我们尽量避免对const的重新解释。
(3)放在类内部的常量有什么限制?
看看下面这个例子:
class A
{
private:
const int c3 = 7; // ???
static int c4 = 7; // ???
static const float c5 = 7; // ???
......
};
你认为上面的3句对吗?呵呵,都不对!使用这种类内部的初始化语法的时候,常量必须是被一个常量表达式初始化的整型或枚举类型,而且必须是static和const形式。这显然是一个很严重的限制!
那么,我们的标准委员会为什么做这样的规定呢?一般来说,类在一个头文件中被声明,而头文件被包含到许多互相调用的单元去。但是,为了避免复杂的编译器规则,C++要求每一个对象只有一个单独的定义。如果C++允许在类内部定义一个和对象一样占据内存的实体的话,这种规则就被破坏了。

(4)如何初始化类内部的常量?
一种方法就是static 和 const 并用,在内部初始化,如上面的例子;
另一个很常见的方法就是初始化列表:
class A
{
public:
A(int i="0"):test(i) {}
private:
const int i;
};
还有一种方式就是在外部初始化,例如:
class A
{
public:
A() {}
private:
static const int i; file://注意必须是静态的!
};
const int A::i=3;
(5)常量与数组的组合有什么特殊吗?
我们给出下面的代码:
const int size[3]={10,20,50};
int array[size[2>;
有什么问题吗?对了,编译通不过!为什么呢?
const可以用于集合,但编译器不能把一个集合存放在它的符号表里,所以必须分配内存。在这种情况下,const意味着"不能改变的一块存储"。然而,其值在编译时不能被使用,因为编译器在编译时不需要知道存储的内容。自然,作为数组的大小就不行了:)
你再看看下面的例子:
class A
{
public:
A(int i="0"):test[2]({1,2}) {} file://你认为行吗?
private:
const int test[2];
};
vc6下编译通不过,为什么呢?
关于这个问题,前些时间,njboy问我是怎么回事?我反问他:"你认为呢?"他想了想,给出了一下解释,大家可以看看:我们知道编译器堆初始化列表的操作是在构造函数之内,显式调用可用代码之前,初始化的次序依据数据声明的次序。初始化时机应该没有什么问题,那么就只有是编译器对数组做了什么手脚!其实做什么手脚,我也不知道,我只好对他进行猜测:编译器搜索到test发现是一个非静态的数组,于是,为他分配内存空间,这里需要注意了,它应该是一下分配完,并非先分配test[0],然后利用初始化列表初始化,再分配test[1],这就导致数组的初始化实际上是赋值!然而,常量不允许赋值,所以无法通过。
呵呵,看了这一段冠冕堂皇的话,真让我笑死了!njboy别怪我揭你短呀:)我对此的解释是这样的:C++标准有一个规定,不允许无序对象在类内部初始化,数组显然是一个无序的,所以这样的初始化是错误的!对于他,只能在类的外部进行初始化,如果想让它通过,只需要声明为静态的,然后初始化。
这里我们看到,常量与数组的组合没有什么特殊!一切都是数组惹的祸!
(6)this指针是不是const类型的?
this指针是一个很重要的概念,那该如何理解她呢?也许这个话题太大了,那我们缩小一些:this指针是个什么类型的?这要看具体情况:如果在非const成员函数中,this指针只是一个类类型的;如果在const成员函数中,this指针是一个const类类型的;如果在volatile成员函数中,this指针就是一个volatile类类型的。
(7)const到底是不是一个重载的参考对象?
先看一下下面的例子:
class A
{
......
void f(int i) {......} file://一个函数
void f(int i) const {......} file://上一个函数的重载
......
};
上面是重载是没有问题的了,那么下面的呢?
class A
{
......
void f(int i) {......} file://一个函数
void f(const int i) {......} file://?????/
......
};
这个是错误的,编译通不过。那么是不是说明内部参数的const不予重载呢?再看下面的例子:
class A
{
......
void f(int& ) {......} file://一个函数
void f(const int& ) {......} file://?????/
......
};
这个程序是正确的,看来上面的结论是错误的。为什么会这样呢?这要涉及到接口的透明度问题。按值传递时,对用户而言,这是透明的,用户不知道函数对形参做了什么手脚,在这种情况下进行重载是没有意义的,所以规定不能重载!当指针或引用被引入时,用户就会对函数的操作有了一定的了解,不再是透明的了,这时重载是有意义的,所以规定可以重载。
(8)什么情况下为const分配内存?
以下是我想到的可能情况,当然,有的编译器进行了优化,可能不分配内存。
A、作为非静态的类成员时;
B、用于集合时;
C、被取地址时;
D、在main函数体内部通过函数来获得值时;
E、const的 class或struct有用户定义的构造函数、析构函数或基类时;。
F、当const的长度比计算机字长还长时;
G、参数中的const;
H、使用了extern时。
不知道还有没有其他情况,欢迎高手指点:)

(9)临时变量到底是不是常量?
很多情况下,编译器必须建立临时对象。像其他任何对象一样,它们需要存储空间而且必须被构造和删除。区别是我们从来看不到编译器负责决定它们的去留以及它们存在的细节。对于C++标准草案而言:临时对象自动地成为常量。因为我们通常接触不到临时对象,不能使用与之相关的信息,所以告诉临时对象做一些改变有可能会出错。当然,这与编译器有关,例如:vc6、vc7都对此作了扩展,所以,用临时对象做左值,编译器并没有报错。
(10)与static搭配会不会有问题?
假设有一个类:
class A
{
public:
......
static void f() const { ......}
......
};
我们发现编译器会报错,因为在这种情况下static不能够与const共存!
为什么呢?因为static没有this指针,但是const修饰this指针,所以...
(11)如何修改常量?
有时候我们却不得不对类内的数据进行修改,但是我们的接口却被声明了const,那该怎么处理呢?我对这个问题的看法如下:
1)标准用法:mutable
class A
{
public:
A(int i="0"):test(i) { }
void Setvalue(int i)const { test="i"; }
private:
mutable int test; file://这里处理!
};
2)强制转换:const_cast
class A
{
public:
A(int i="0"):test(i) { }
void Setvalue(int i)const
{ const_cast (test)=i; }//这里处理!
private:
int test;
};
3)灵活的指针:int*
class A
{
public:
A(int i="0"):test(i) { }
void Setvalue(int i)const
{ *test=i; }
private:
int* test; file://这里处理!
};
4)未定义的处理
class A
{
public:
A(int i="0"):test(i) { }
void Setvalue(int i)const
{ int *p=(int*)&test; *p=i; }//这里处理!
private:
int test;
};
注意,这里虽然说可以这样修改,但结果是未定义的,避免使用!
5)内部处理:this指针
class A
{
public:
A(int i="0"):test(i) { }
void Setvalue(int i)const
{ ((A*)this)->test=i; }//这里处理!
private:
int test;
};
6)最另类的处理:空间布局
class A
{
public:
A(int i="0"):test(i),c('a') { }
private:
char c;
const int test;
};
int main()
{
A a(3);
A* pa=&a;
char* p=(char*)pa;
int* pi=(int*)(p+4);//利用边缘调整
*pi=5; file://此处改变了test的值!
return 0;
}
虽然我给出了6中方法,但是我只是想说明如何更改,但出了第一种用法之外,另外5种用法,我们并不提倡,不要因为我这么写了,你就这么用,否则,我真是要误人子弟了:)
(12)最后我们来讨论一下常量对象的动态创建。
既然编译器可以动态初始化常量,就自然可以动态创建,例如:
const int* pi="new" const int(10);
这里要注意2点:
1)const对象必须被初始化!所以(10)是不能够少的。
2)new返回的指针必须是const类型的。
那么我们可不可以动态创建一个数组呢?
答案是否定的,因为new内置类型的数组,不能被初始化。

更多相关推荐:
c&c++中const用法总结

const类型定义:指明变量或对象的值是不能被更新,引入目的是为了取代预编译指令**************常量必须被初始化*************************cons的作用(1)可以定义cons…

const用法总结

const看到const关键字很多程序员想到的可能是const常量这可有点象踩到陷井上还不知道自己危险了读读以下文字会使你对c中的const有一个全面的认识const是C中常用的类型修饰符有某些微妙的应用场合如...

C++中const用法总结

C中const用法总结作者JuKevin1const修饰普通变量和指针const修饰变量一般有两种写法constTYPEvalueTYPEconstvalue这两种写法在本质上是一样的它的含义是const修饰的...

c++const用法小结

C中const的用法小结来源本站原创编辑本站编辑时间20xx09241const常量如constintmax100优点const常量有数据类型而宏常量没有数据类型编译器可以对前者进行类型安全检查而对后者只进行字...

C++中const用法总结

C中const用法总结思维方式是什么为什么怎么用C中有些什么东西const可以修饰些什么什么原理谁变谁不变有什么好处C中有些什么数据变量常量字面量函数方法代码块常量101aabc先不讨论const定义的常量变量...

C++中const用法总结

2指针使用CONST1指针本身是常量不可变charconstpContentconstcharpContent2指针所指向的内容是常量不可变constcharpContentcharconstpContent3...

C++中const用法总结

C中const用法总结月光林地博客园1const修饰普通变量和指针const修饰变量一般有两种写法constTYPEvalueTYPEconstvalue这两种写法在本质上是一样的它的含义是const修饰的类型...

Const的用法大全

详解Const的用法SunnymanConst限定符主要是声明变量为只读它的用法我归纳学习了一下主要表现在以下几个方面1限定符声明变量只能被读constinti3声明i为一个只读变量但i不是常量而且这个变量必须...

const用法

使用const提高函数的健壮性看到const关键字C程序员首先想到的可能是const常量这可不是良好的条件反射如果只知道用const定义常量那么相当于把火药仅用于制作鞭炮const更大的魅力是它可以修饰函数的参...

const用法详解

const用法详解转面向对象是C的重要特性但是c在c的基础上新增加的几点优化也是很耀眼的就const直接可以取代c中的define以下几点很重要学不好后果也也很严重const1限定符声明变量只能被读consti...

Const用法

const用法详解面向对象是C的重要特性但是c在c的基础上新增加的几点优化也是很耀眼的就const直接可以取代c中的define以下几点很重要学不好后果也也很严重const1限定符声明变量只能被读constin...

const用法

1什么是const常类型是指使用类型修饰符const说明的类型常类型的变量或对象的值是不能被更新的当然我们可以偷梁换柱进行更新2为什么引入constconst推出的初始目的正是为了取代预编译指令消除它的缺点同时...

const用法总结(44篇)