关键字
有很多,但也不是很多
命名空间
从写hello world开始,就注意到
using namespace std;
的存在。在我理解中,命名空间就像是创建了许多文件夹,有逻辑地将变量、函数和类(什么是类?)归入其中,避免命名冲突(字面意思)。
namespace N1
{
\\在命名空间中定义变量
int a;
\\在命名空间中定义函数
int Nothing(int a)
{
return a;
}
\\在命名空间中嵌套命名空间
namespace N2
{
int b;
}
}
\\同名空间将被在编译时合并
namespace N1
{
int c;
}
使用命名空间的三种途径
N::a;
using N::b;
using namespace N;
C++输入与输出
#include <iostream>
using namespace std;
int main()
{
cout<<"Hello world!"<<endl;
}
cout和cin包含在iostream头文件以及std命名空间中。c++输入输出不需要增加数据格式控制,好爽。
缺省参数
一个功能俱全的函数往往有许多参数不需要在每一次调用时都进行传递。于是为此类参数赋默认值会很省事儿。在半缺省参数的情况下,必须从右往左放置缺省参数。
void test(int a, int b =0, int c = 0)
{
cout<<a<<endl<<b<<endl<<c<<endl;
}
为了不迷惑编译器,缺省参数不同时出现在定义和声明中。且缺省值必须是常量或者全局变量。
函数重载
在同一作用域中,c++允许多个功能类似的同名函数的存在,其形参列表必须不同。这样的设计可以应多数据类型不唯一的情况。c++中为了保证底层的全局唯一性,使用了教c语言更为复杂的名字修饰手段,将函数形参类型等信息也包含其中。因此在同名函数的使用情境中,一定要保证其形参列表不相同。
引用
引用是给被引用变量取得一个别名, 与被引用对象共用同一内存空间。
具体要求:1. 定义是必须初始化;2. 一个变量可以有多个引用;3. 引用一旦建立,不能引用其他实体。
int a = 10;
int& ra = a;
int& rra = a;
const int b = 10;
const int& rb = b;
const int& rc = 10;
double d = 3.14;
const int& rd = d;
//这样的引用方式的结果是d和rd的地址不一样,d和rd的地址之差恒定(与数据类型组合有关)
引用可以用作函数的参数,也可以做返回值。当函数返回一个引用时,实际上一个指向返回值的隐式指针被返回,如此一来,函数便可以被放在赋值语句的左边,而该返回值可以被因此溯源改变。
目前测试发现引用的效率高于指针。以下程序比较指针和引用作为函数返回值是的效率:
#include <iostream>
#include <time.h>
#include <Windows.h>
using namespace std;
struct A
{
int a[10000];
};
A a;
A Test1()
{
return a;
}
A& Test2()
{
return a;
}
void Test()
{
size_t begin1 = clock();
for (size_t i = 0; i < 100000; ++i)
Test1();
size_t end1 = clock();
size_t begin2 = clock();
for (size_t i = 0; i < 100000; ++i)
Test2();
size_t end2 = clock();
cout << "Pointer time\t" << end1 - begin1 << endl;
cout << "Reference time\t" << end2 - begin2 << endl << endl;
}
int main()
{
for (int i = 0; i < 10; ++i)
{
Test();
}
Sleep(10000);
return 0;
}
个人理解:指针由于要另辟一块内存用于存放地址,效率要低于没有实体空间的引用。
const和引用
引用好比,对于同一个人(int),他又不同的名字(a, ra, rra),有的名字是变量性质(int& ra = a;),有的名字时常量性质(const int& rra = a;)。当你喊他变量名字(ra)的时候,你可以给他剪头发,整容,卸胳膊卸腿;而当你喊他常量名字(rra)的时候,他是金刚不坏之身。但是这些情况下并不出现新的内存区。实体还是他这个人(int)。
int a = 10;
int& ra = a; //起个外号
const int& rra = a; //再起个外号
a = 11;
ra = 12; //你可以随便改它
//rra = 13; //此时你无法伤害它
而更变态的是,你可以通过(const double rrra = a;)来改变他作为人的这个属性,把他变成一个猴子。那么这个时候,会出现一个新的实体,存放于一个不同的地址中。当你喊出这个名字(rrra)的时候,会有一个猴子回过头看你,而这个人并不搭理你。然而这个猴子是个金刚不坏之身。有趣的是,这个猴子的地址不是随机出现的,而是与这个人的地址保持一个不变的地址差距。这个地址差距会因为数据类型组合(int与double,或者char与int)的不同而变化。
const double& rrra = a;
printf("%d\n", &a);
printf("%d\n", &rrra);
//此时输出值会有差异,差异恒定,输出值随机
而更加令我没有想到的是,当你重复这个把人变成猴子的过程时,你会创造出第二个猴子,而不是仅仅给第一个猴子起了个新名字。当然,你也可以给第二个猴子起新名字,这并不奇怪。你也可以把人变成鸡,把鸡变成猴子,再把猴子变成人。而这个新人,则会有新的地址。