C++中几个重要的关键字总结

时间:2014.04.05

地点:基地二楼

----------------------------------------------------------
一、const关键字

const指保持不变的量,任何试图做出改变的行为都会当做错误处理,此外当启用优化的时候,编译器可以利用这种信息生成更好的代码。

1.const变量以及参数

可以用const保护变量不被修改,用于代替#define,比如:

const dpuble PI=3.14159;
还可以使用const指定函数和方法的参数保持不变。比如:

void func(const int param)
{ 
    //
}
这样你就不能修改整数param了。

2.const指针

const int *p;
表示指针指向一个 const int 类型的变量,由此说明我们不能通过该指针试图去改变这种变量的值。

一种等价的写法是

int const* ip;
我的一种理解是,在星号前面的部分都是用了说明这个指针是指向什么类型的变量的。

如果想限制指针本身是一个常量,那就要让const靠近指针变量名,而不是去修饰指向什么类型的部分。比如:

int* const ip=nullptr;
当然上面这样让一个指针保持为空是毫无意义的,但至少可以说明问题,ip是一个常量,它的值是天生的不可以被改变,即在第一次声明时初始化后不能再被改变,指向的类型说明部分在星号前面,是int类型的。
另外也还可以将指针所指的值全部标记为const,比如:

int const* const ip=nullptr;
等价的写法是:

const int* const ip=nullptr;
也就是说 const和类型nt在一起玩时,他们的次序是无关紧要的。
当我们阅读时可以这样,采取从右向左的读法:

int* const ip;
ip是一个常量指针,指向一个int

int const* ip;
ip是一个指针,指向一个const int

3. const 引用

引用是被默认为const的,你无法改变引用所指的对象,因此不允许显式地将引用标记为const。const引用如下:

int z;
const int& zRef=z;
这里将const应用到int,因此我们无法再去对zRef赋值,同样这里const和int的顺序是无关紧要的。然而我们只是说通过zRef不能去修改z的值,通过z自身还是可以的。

当将对象作为参数时,首先应该考虑const引用,只有在明确需要修改对象时才可以忽略,按引用传递某个值,可以提高效率。

4.const方法

我们可以将类的方法标记为const,从而禁止方法修改类的任何非可变数据成员。

----------------------------------------------------------

二、static关键字

  static有很多种用法,这些用法之间也并没有太多联系,而“重载”关键字的部分原因是避免在语言中引入新的关键字。

1.静态数据成员和方法

静态数据成员不属于对象的一部分,它存在于对象之外,但在类之中,从属于类这个层次,所有这一类的对象共享这一个副本。静态方法也是一样。

2.静态链接

C++中每个源文件都是单独编译的,编译得到的目标文件会彼此进行链接。每个源文件中的每个名称,包括函数以及全局变量,都有一个内部或者外部的链接。外部链接意味着这个名称在其它源文件中也有效,内部链接(即静态链接)意味着这些名称在其它源文件中无效。默认情况下,函数和全局变量都是拥有外部链接的。但是一经过使用关键字static的声明,会指定为内部(或者静态)链接。例如,假设现在有两个源文件,FirstFile.cpp以及AnotherFile.cpp

//FisrstFile.cpp
void f();
int main()
{
  f();
  return 0;
}
该文件只提供了f()的原型,并没有给出定义。

下面是AnotherFile.cpp

#include<iostream>
using namespace std;
void f();
void f()
{
  cout<<"f\n";
}
该文件同时提供了f()的原型和定义。

在两个不同文件中编写相同函数的原型是合法的。如果将原型放在头文件中,并且每个源文件都用#include包含这个头文件,预处理器会自动在每个源文件中给出函数原型。使用头文件的原因是便于维护和保持同步原型的一个副本。

  以上两个源文件都会编译成功,程序链接也没有问题,因为f()具有外部链接,第一个源文件中的fmain()可以从另外一个文件调用这个函数。现在假定在AnotherFile.cpp中将f()用static修饰,即:

#include<iostream>
using namespace std;
static void f();
void f()
{
  cout<<"f\n";
}
这样之后每个源文件都会编译成功,但链接时会出问题,因为被static修饰后的f()具有内部(静态)链接,FirstFile.cpp无法使用这个函数,而它自己却没有定义这个函数,只是声明了。与static这一效果等效的做法是使用匿名名称空间。比如:

#include<iostream>
using namespace std;
namespace
{
  void f();
  void f()
    {
        cout<<"f\n";
    }
}
同一文件中,可在匿名名称空间之后的任何位置访问名称空间中的项,但不可以在其他文件中访问,和static的语义是一样的。

3.函数中的静态变量

函数中的静态变量最终目的是创建一个:离开和进入作用域都可以保留值得局部变量。就好像一个只能在函数内部访问的全局变量一样,表现得像一个全局变量,但只有该函数才能有权限访问。函数中的静态变量最常见的用法就是“记住”某个函数是否执行了特定的初始化操作。比如:

void PerformTask()
{
  static bool inited=false;
  if(!inited)
    {
       cout<<"initiong\n";
       inited=true;
     }
}
但是静态变量容易让人迷惑,更好的办法是避免使用静态变量,用类的构造函数方法执行所需要的操作。

----------------------------------------------------------

三、extern关键字

  extern关键字与static关键字相反,它将名称指定为外部链接。通常const和typedef在默认情况下视内部链接,也就是说,普通情况下变量们是外部链接的,但cosnt和typedef修饰的变量将是内部链接,为了可以让他们外部链接,可以使用extern使其变为内部链接。但使用extern时有点复杂,当指定某个名称为extern时,编译器会当这是声明,不会为之分配空间,我们必须为这个变量提供单独的,不使用extern关键字的定义行。比如:

extern int x;
int x=3;

----------------------------------------------------------

四、非局部变量的初始化顺序

  程序中的所有全局变量以及类的静态数据成员都会在main()开始之前初始化。给定源文件中的变量以在源文件中出现的顺序初始化。但不同源文件中非局部变量的初始化顺序是不确定的。












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值