照理说有const的参数怎么还能执行*strDest++=*strSrc++;呢 请大师解答c++
char* Copy(char* strDest,const char* strSrc) { char* strDestCopy = strDest; while (*strSrc!='\0') { *strDest++=*strSrc++; } return strDestCopy; }
首先,你得先区分const char* a和char* const a的区别。 一个是把指针定为const 。就是不能修改指针。也就是char * const p 一个是把指针指向的内容定为const 。就是不能修改指针指向的内容 也就是const char p 在这里,const char strSrc表示的是不能修改指针指向的内容,可是对于*strDest++=*strSrc++; 只是在修改指针strSrc的指向,因此是能够成立而且执行的,不明白继续追问程序员
是一道专接本的简答题,要求至少说出两种const的用途函数
还有一道题是软件测试都有哪些种类 请高手帮忙 fsyss1314 | 浏览 162269 次 发布于2015-05-17 22:48 最佳答案测试
const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。设计
const关键字的做用主要有如下几点:指针
(1)能够定义const常量,具备不可变性。 例如: const int Max=100; int Array[Max]; (2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。例如: void f(const int i) { .........} 编译器就会知道i是一个常量,不容许修改; (3)能够避免意义模糊的数字出现,一样能够很方便地进行参数的调整和修改。 (4)能够保护被修饰的东西,防止意外的修改,加强程序的健壮性。 仍是上面的例子,若是在函数体内修改了i,编译器就会报错; 例如: void f(const int i) { i=10;//error! } (5) 为函数重载提供了一个参考。 class A { ...... void f(int i) {......} //一个函数 void f(int i) const {......} //上一个函数的重载 ...... }; (6) 能够节省空间,避免没必要要的内存分配。 例如: #define PI 3.14159 //常量宏 const doulbe Pi=3.14159; //此时并未将Pi放入ROM中 ...... double i=Pi; //此时为Pi分配内存,之后再也不分配! double I=PI; //编译期间进行宏替换,分配内存 double j=Pi; //没有内存分配 double J=PI; //再进行宏替换,又一次分配内存! const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define同样给出的是当即数,因此,const定义的常量在程序运行过程当中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。 (7) 提升了效率。 编译器一般不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操做,使得它的效率也很高。code
const 更大的魅力是它能够修饰函数的参数、返回值,甚至函数的定义体。对象
const 是constant 的缩写,“恒定不变”的意思。被const 修饰的东西都受到强制保护,能够预防意外的变更,能提升程序的健壮性。因此不少C++程序设计书籍建议:“Use const whenever you need”。内存
##1、const 修饰函数的参数get
若是参数做输出用,不论它是什么数据类型,也不论它采用下文讨论的“指针传递”仍是“引用传递”,都不能加const 修饰,不然该参数将失去输出功能。const 只能修饰输入参数,这又分为如下几种状况。
1.1 const 用于修饰“指针传递”的参数,以防意外改动指针所指数据
例如某个 StringCopy 函数:
void StringCopy(char *strDestination, const char *strSource);
其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,若是函数体内的语句试图改动 strSource 的内容,编译器将指出错误。
固然也有方法绕过这个限制,例如能够在函数体内重命名一个指针 char * strSource2 = strSource ; 便可改动 strSource 所指的数值。
1.2 const 用于修饰“指针传递”的参数,以防意外改动指针自己
考虑以下代码:
void swap ( int * const p1 , int * const p2 )
该定义将限制在函数 swap 内修改指针 p1 和 p2 的指向。
1.3 值传递的效率问题
若是输入参数采用“值传递”,因为函数将自动产生临时变量用于复制该参数,该输入参数原本就无需保护,因此不要加const 修饰。
例如不要将函数 void Func1 (int x) 写成 void Func1(const int x)。同理不要将函数 void Func2(MyClass a) 写成void Func2(const MyClass a)。其中 MyClass 为用户自定义的数据类型。
然而,对于非内部数据类型的参数而言,相似 void Func(MyClass a) 这样声明的函数效率会比较底,这是由于函数体内将产生MyClass类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。
为了提升效率,能够将函数声明改成void Func (MyClass &a),由于“引用传递”仅借用一下参数的别名而已,不须要产生临时对象。
可是函数void Func(MyClass & a) 存在一个缺点:“引用传递”有可能改变参数a,这是咱们不指望的。
解决这个问题很容易,加const修饰便可,所以函数最终成为void Func(const MyClass &a)。
以此类推,是否应将void Func(int x) 改写为void Func(const int &x),以便提升效率?
答案是彻底没有必要,由于内部数据类型的参数不存在构造、析构的过程,而复制也很是快,“值传递”和“引用传递”的效率几乎至关。因此对于内部数据类型的输入参数,不要将“值传递”的方式改成“const 引用传递”。不然既达不到提升效率的目的,又下降了函数的可理解性。
##2、const 修饰函数的返回值
2.1 const 修饰函数返回值(返回指针)
若是给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
例如函数
const char * GetString(void);
以下语句将出现编译错误:
char *str = GetString();
正确的用法是
const char *str = GetString();
2.2 const 用于修饰“返回引用”函数的返回值
若是函数返回值采用“值传递方式”,因为函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值。例如把函数int GetInt(void) 写成const int GetInt(void)是没有意义的。
若是返回值不是内部数据类型,将函数MyClass GetObj(void) 改写为const Myclass & GetObj(void)的确能提升效率。但此时千万千万要当心,必定要搞清楚函数到底是想返回一个对象的“拷贝”仍是仅返回“别名”就能够了,不然程序会出错。
这里对函数返回值使用 const 的目的在于限制不能将函数调用表达式做为左值使用。例若有以下函数:
int & min ( int &i, int &j);
能够对函数调用进行赋值,由于它返回的是左值: min ( a , b )=4;
可是,若是对函数的返回值限定为 const 的,即丁奕:const int & min ( int & i, int &j );
那么,就不能对 min ( a, b ) 调用进行赋值了。
事实上,函数返回值采用“引用传递”的场合并很少,这种方式通常只出如今类的赋值函数中,目的是为了实现链式表达。
例如:
class A { A & operate = (const A & other); // 赋值函数 } ; A a, b, c; // a, b, c 为A 的对象 a = b = c; // 正常的链式赋值 (a = b) = c; // 不正常的链式赋值,但合法
若是将赋值函数的返回值加const 修饰,那么该返回值的内容不容许被改动。上例中,语句 a = b = c 仍然正确,可是语句 (a = b) = c 则是非法的。
const 成员函数的声明看起来怪怪的:const 关键字只能放在函数声明的尾部,大概是由于其它地方都已经被占用了。
但事实上,任何不会修改数据成员(即函数中的变量)的函数都应该声明为const 类型。若是在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提升程序的健壮性。
例以下面的类MyClass的成员函数getCount(): 1 2 3 4 5
class MyClass { int member ; public: int getCount ( ) const; };
这里,在函数定义头后面加上的 const 表示这个函数是一个“只读函数”,函数不能改变类对象的状态,不能改变对象的成员变量的值。如在函数体中不能这么写: 1 2 3 4
classname :: getCount( ) { member =4 ; return member; }
编译器将指出getCount 函数中的错误,由于试图修改数据成员member。一样,const成员函数也不能在函数中调用其余非const 的函数。