Const关键修饰变量常用功能
-
const关键字通常用来修饰变量、函数。当用来修饰变量则向编译器表示此变量为不可以修改内存数据,内存数据相当于只读属性。
-
const关键字修饰的变量或对象不影响该变量的生命周期。但影响变量的作用域 。使用const关键修饰的全局变量在不同文件中使用,需要显式的声明为extern属性,且必须定义时已经初始化。普通的全局变量默认即为extern属性所以不需要显式的说明即可以在不同文件中使用,且普通变量声明可初始化,也可不初始化变量。
-
const修饰的变量由于是只读属性,相当于define宏定义功能。const修饰的变量编译器需在使用时进行类型检查,但define宏定义只是简单编译时变量或代码替换。使用const修饰变量使之成为只读变量代替define宏功能会更安全。
在使用const关键时c/c++的使用些不同之处,这些不同之处由于语言特性决定详细再聊。
Const修饰词与指针
const修饰的指针指针变量:一种修饰指针指向的内容;一种是指针变量本身被const关键字修饰而不能更改。
这里以变量的定义来说明。
const int age;
const int* age; //等同int const *age
const int* const age
const与指针的关键有时会混淆,主要是理清const修饰的指针变量本身,还是修饰指针变量指向的内存空间。如果修饰指针则指针无法再指向其它内存区域。如果修饰的是指针指向的内存区域则是内存数据不可以更新,但指针变量指向内存空间可以更改。
const修饰的指针本身还是指针指向的内存,是由指针变量的标识符*决定。
这里需要理解一些指针相关的知识:
int age //表示age是一个整型变量,即age的类型为int型,即内存存放的数据为int型。
int* age //表示age是一个指针变量,即age的类型为int*型,指针指向的内存区域的数据类型为int型。
可以看到普通变量只表示内存区域存放的数据类型,但指针不仅表示了变量类型,还表示了指针指向内存域数据类型。(类型才是代表数据是如何存放于内存中。)
const int* const age; 这定义是以*号为划分来解析。const age即修饰指针变量(指针变量也只是一个普通的变量而已,占4字节)。即指针变量为只读属性无法再指向别的内存区域。另外一部分是const int * 则为指针变量指向的内存数据为只读属性(int * 相当于解引用内存区域,加const即修饰了内存区域的数据为只读)。
const在c++的使用
在c++的使用中除修饰一般的变量以外,还常用来修饰对象中的方法。用来防止函数对变量成员的非法修改。与const修饰变量相似,const修饰成员函数则成员函数本身无法使用修改成员变量的语句,即const成员函数只能用来读取数据。
相似的const修饰对象实例,则该实例只能使用带const关键个字修饰的成员函数。这样也是很好理解的,定义成const说明整个对象实例都是只读的,如果能调用其它非const修饰的函数则有可能在函数中更改了对象的数据成员,这个初衷是相违背的。所以const object只能使用const修饰的函数。
#include <iostream>
#include <string>
#include <string.h>
#include <thread>
using namespace std;
namespace zj002{
class Copy{
public:
Copy(const char* str, int var);
Copy(const Copy& cp);
~Copy();
void showInfo() const {cout << "Copy name addr:" << name << endl;}
void setInfo(const char* str) {strcpy(name, str);};
private:
char* name;
int age;
}; /* end class declared */
Copy::~Copy()
{
//delete[] name;
//name = nullptr;
cout << "Destry addr:" << static_cast<void*>(name) << endl;
}
Copy::Copy(const char* str, int var)
{
if(str){
name = new char[strlen(str) + 1];
strcpy(name, str);
}
else{
name = new char[1];
*name = '\0';
}
age = var;
}
Copy::Copy(const Copy& cp)
{
name = new char[strlen(cp.name) + 1];
strcpy(name, cp.name);
age = cp.age;
}
} /* end namespace zj001 */
using namespace zj002;
void constFunc()
{
const int age = 10; // const int age -> uninitialized const 'age'
//age = 20 ->assignment of read-only variable
}
void constPointerFunc()
{
const char* name = "zhangsan";
const char* const ptr = new char[strlen(name) + 1];
// ptr = name; -> assignment of read-only variable
//strcpy(ptr,name); -> invalid conversion from 'const char*' to 'char*'
cout << "The ptr:" << ptr << endl;
}
int main(int argc, char** argv)
{
const Copy fp("tudou", 32);
//fp.setInfo("jerry"); -> passing 'const zj002::Copy' as 'this' argument discards qualifiers
fp.showInfo();
constPointerFunc();
puts("-------------------------------");
return 0;
}