单独编译
c++的编译时单独的,把编译好的文件在通过链接器的东西链接起来就成了一个可以跑的程序,所以我们一般把源代码写在下面两个文件中(只是名字不同罢了)
头文件:包括结构声明和使用这些结构的函数原型
源代码文件:包含与结构有关的函数代码
上面这两个名词是一个很好用的组织程序策略。我们把下面这些东西放在头文件中
1函数原型
2使用#define 或const定义的符号常量
3结构声明
4类声明
5模板声明
6内联函数
存储持续性,作用域,链接性
持续性
1自动存储持续性
c++中定义生命的变量 ,在程序执行其所属的函数和代码块是被创建,执行完函数和代码块是被释放,c++有两种存储持续性为自动的变量
2静态存储持续性
在函数外定义的变量或者使用关键词为static定义的变量存储持续性为静态,他们在整个运行过程中都存在 c++有三种存储持续性为静态的变量
3线程存储持续性
thread_local声明的变量,则其生命周期与所属线程生命周期一样长
4动态存储持续性
new 运算符 创建的变量在再heap中 除非用delete释放
reigister
作用域和链接
说完怎么多之后我们就对变量就有了大体的认识了 ,现在开始讲变量持续的分类吧
自动存储持续性
这种类型的变量一般都是代码块中的变量 ,因为他们的生存周期和作用域的是随着代码块的的周期而开始和消亡的,典型的就是函数中的参数,他们的持续性是自动的,作用域是局部的,没有链接性(一般自动变量是通过栈stack实现的)
静态存储持续性
静态变量的初始化
c++11 增加constexpr关键字,增加了创建常量表达式的方法(我也不知道干什么用的)
单定义规则
单定义规则就是 编译器必须准确的找到变量不能出现二义性
一方面,在每个使用外部变量中,都必须声明它,另一方面,变量只能有一次定义,为满足这种需求,c++提供两种变量声明,一种是定义声明 ,简称定义,他给变量分配存储空间;另一种引用声明简称声明 他不给变量存储空间
引用声明 关键字extern
如果要在多个文件中使用外部变量,只需在一个文件中包含变量定义,在使用该变量的其他文件中都必须使用extern声明它,这个主要就是用在链接性为外部的变量不重复定义的一项技术 代码就不写了 以后你们在各种实践中就知道怎么用了
说明符和限定符
存储说明符
struct A{
int a;
mutable int b;
}
const A s={1,0};
s.b++;
cv-限定符
现在专门说说cv限定符(const和volatile),const就不多说了,那么volatile是什么呢,英文意思易变得。在计算机中一个内存地址存储着一些重要消息,而这个地址很可能会时不时的被硬件改写,亦或是两个程序在互相修改这个地址里的信息,而有些编译器会做一些优化,他发现代码中有两个地方使用了同一个变量的值,他会做一个优化,把这个变量存到寄存器。方便读取也保证了值得不变,而volatile就是取消这种优化的。
基本上说完了,但是不知道有没有人发现一个问题。如果我们在头文件中定义一个常量 const int n=1;那么我们在其他源代码文件中导入这个头文件,之后再编译链接,程序会怎么样呢,答案是通过了也运行良好?为什么呢?有人可能问什么为什么。想上面这样定义的的 n。他应该是文件共享的,也就是说最后的编译结果是有很多n,根据单定义规则则是错误的。为什么呢?原因很简单c++做出了特殊的规定const修饰的变量它的链接性就变成了内部的,这就ok了
函数的链接性
语言链接性
简单的说c++或者c语言在对于名字相同的函数重载在内部实现是用不同的名称来定义的。为了让c++可以根据人的意图来 使用c++还是c语言命名规则的话 就可以用如下代码
extern "C" void f();
extern "C++"void f();
extern void f();
起始页可以用其他说明符,只是上面是c++标准的说明符
用new来完成动态分配
int*p=new int();//动态分配
new * operator new (std::size_t)
new * operator new[](std::size_t)
int *p=new int
int *pp=new int[40]
int *p=new(sizeof(int))
int*p=new(40*szieof(int))
int a;
int[ aarray30];
int *p=new(a)int ;
int parray=new(aarray)int;//数组名师第一个元素的地址
名称空间
什么是名称空间, 这个就好像两个相同名字的小孩拥有不同名字的爸爸一样 。比如std::out中std就是名称空间(爸爸)的名字而::是作用域解释符(爸爸和孩子之间的纽带)后面的cout就变量(孩子)的名字,再叫小孩的时候我们就可以叫某某的儿子了。
如何创建
在c++中我们定义一种新的声明空间来创建命名空间
namespace A{
int a;
double b;
struct C{};
}
1名称空间可以是全局的,也可以位于另一个名称空间中,但是不能再代码块中,因此默认情况下名称空间的连接性为外部(除非他引用了常量)。
2名称空间是开放的,你可以在以后继续添加东西 。例如你可以在头部的名称空间定义函数原型,再在后面的程序中往名称空间添加定义。
using声明和using编译指令
using std::cout;//接下来代码块中的cout使用的都是std::cout;
using namespace std;//接下来代码块中使用的都是std里面的变量(如果有的话);
using声明和using编译指令的比较
namespace A{ int a; }
int a;
int main(){
using namespace A;
int a;
cout<<a <<endl;
cout<<::a<<endl;
cout<<A:;a<<endl;
return;
}
所以使用using声明比较安全
名称空间的特殊性质
名称空间中可以使用名称空间
namespace C{
using A::a;
using namespace B;
using std::cout;
using std::cin;
}
编译指令时可以传递的
using namespace C;
等价于
using namespace C;
using namespace B;
还有名称空间可以相互赋值的,这样可以简化名称空间嵌套的代码量
namespace D=C::B::a;
using D::a;
using A::a;
未命名的名称空间