(8)C++ 内存模型与名称空间
一、单独编译
头文件
不要将函数定义或者变量声明放到头文件中,引入多个文件时可能会造成同一个函数定义多次
引入头文件
#include "文件名"
File1.h
#ifndef FILE1_H_
#define FILE1_H_
struct Student
{
int age;
};
#endif // !FILE1_H_
File2.h
#include "File1.h"
main.cpp
#include<iostream>
#include "File1.h"
#include "File2.h" using namespace std; void main() {
Student stu = {};
cout << stu.age << endl;
}
这里的
#ifndef FILE1_H_ .....code
#endif
如果File2.h引入了头文件File1.h,并且main.cpp 同时引入了File1和File2两个头文件,这样会导致 Stuendt 会引入两回,编译器遇到这种情况会报编译错误。有了ifndef就会忽略重复引入的问题。
这里的
#define FILE1_H_
当以前没有使用预处理器编译指令#define定义的名称 FILE1_H_时,才处理#ifndef #endif之间的语句。
2.
预编译会把.cpp 引用的头放入 cpp代码中
例如 file1.cpp file2.cpp 都包含了 test.h 则,test.h的代码即会添加到file1文件,也会添加到file2文件。
二、作用域
作用域:变量等的使用范围。
链接性:外部链接性(变量作用范围)可在文件间共享---全局变量,内部链接性只在当前文件中,无链接性只能在当前函数或代码块中---局部变量。
1.自动变量
函数内声明的变量,作用域只在函数内。
如果代码块内部的变量名和外部的变量名相同,则内部变量作用在内部,外部变量作用在外部
auto a = ; //C++11后相当于 c# var
这种变量存在栈中
2.静态变量
静态变量生命周期比自动变量的寿命更长,静态变量的数目在程序运行期间是不变的,所以不需要栈来管理,编译器会分配固定的内存块来存储它们,默认初始化为0。
(1).如果想有外部链接性的静态变量
必须在外部声明,并且不带static
(2).如果想有内部链接性的静态变量
必须在外部声明,并且带static
(3).如果想有无链接性的静态变量
必须在代码块内部声明,并且带static
#include<iostream>
using namespace std;
int g = ;//具有外部链接性的静态函数
int static a = ;//具有内部链接性的静态函数
void main() { }
void func() {
int static b = ;//无链接性的静态函数
int c = ;//自动变量,
}
3.静态和外部
(1)单定义规则:整个程序中全局变量只能定义一次。
C++有两种变量声明,1是定义声明(简称定义)给变量分配内存空间,2是引用声明(简称声明)不给变量分配内存空间因为它引用已有的变量。
使用extern关键字并且不初始化,表示引用声明。用来表示该变量是来自外部的全局变量
int a = ;//定义声明
extern int b = ; //定义声明,因为进行了初始化
extern int c;//这是真正的引用声明,不分配内存
(2) 如果在文件中声明了一个与外部同名的变量,则该变量属于自动变量
main.cpp
#include<iostream>
using namespace std;
int a = ;
void main() { }
test.cpp
void func1() {
extern int a;//全局变量
}
void func2() {
int a;//自动变量
}
4.静态与内部 5.静态与无链接 略
6.说明符和限定符
volatile、mutable 待补
const
被const修饰的全局变量会变成内部链接性
const int a = ;//内部链接性
void main() { }
7.函数和链接性
C++的链接性为静态的,整个程序执行期间都一直存在。
static 修饰函数可以让函数变成内部的,前提是原型和函数定义必须都加上static
8.语言链接性
C++中查询C++库函数和查询C库的方式不同。要区分它们
extern "C" void fun1();//原型,使用C语言方式查找函数
extern "C++" void fun2();//原型,使用C++方式查找函数
extern void fun3();//原型,默认使用C++方式查找函数
9.动态存储
动态分配的内存由new和delet控制,而不是作用域和链接性的规则控制。
编译器通常使用三块独立内存:静态变量、自动变量、动态存储。(可能会细分)
定位new运算符??
定位new一帮用于以下场合
硬件编程
如果知道了硬件设备的地址,想要将那个硬件设备与一个C++类直接关联,那么定位new就非常有效了
实现基础库
基础库一般为了效率要先预分配内存,然后在预分配的内存上执行构造,几乎所有的C++容器都用到了定位new
三、名称空间
1.C++传统的名称空间
作用域
2.C++名称空间新特性
(1)using声明可以使用单个变量和函数
using声明后在该区域内有效
#include<iostream>
using namespace std;
namespace space1{
int a=;
}
namespace space2 {
int a=;
}
void main() { cout << space1::a;//直接使用
using space2::a;//using声明,避免每次调用时都要加::
cout << a;
}
在外部使用using声明
using space2::a;
void main() { cout << a;//属于space2
} void func1() {
cout << a; //属于space2
}
(2)using 编译可以使用空间下的所有变量和函数
using namespace space2;//使用using编译
void main() {
cout << a;//使用space2下
}
void func1() {
cout << b; //使用space2下
}
如果using编译指令导入一个已经在函数中声明的名称,则会使用局部定义的变量
void main() {
using namespace space2;//
int a = ;
cout << a;//结果 9
}
如果using声明导入一个已经在函数中声明的名称,会报多重错误
void main() {
using space2::a;//
int a = ;
cout << a;//结果 9
}
全局 ::
#include<iostream>
using namespace std;
int a=;
namespace space1 {
int a = ;
int b = ;
} void main() {
using namespace space1;
int a = ;
cout << ::a;//全局的a 结果8
}
尽量使用using声明减少不必要的麻烦
3.名称空间嵌套
4.未命名名称空间
5.名称空间开放性
几个文件都使用namespace 里面的内容可以组合在一起?
6.多文件
(8)C++ 内存模型与名称空间的更多相关文章
- 《C++ Primer Plus》读书笔记之七—内存模型和名称空间
第九章 内存模型和名称空间 1.不要将函数定义或者变量声明放到头文件中. 2.头文件常包含的内容:函数原型.使用#define或者const定义的常量.结构声明.类声明.模板声明.内联函数. 3.避免 ...
- C++ primer plus读书笔记——第9章 内存模型和名称空间
第9章 内存模型和名称空间 1. 头文件常包含的内容: 函数原型. 使用#define或const定义的符号常量. 结构声明. 类声明. 模板声明. 内联函数. 2. 如果文件名被包含在尖括号中,则C ...
- 《C++ Primer Plus》第9章 内存模型和名称空间 学习笔记
C++鼓励程序员在开发程序时使用多个文件.一种有效的组织策略是,使用头文件来定义用户类型,为操纵用户类型的函数提供函数原型,并将函数定义放在一个独立的源代码文件中.头文件和源代码文件一起定义和实现了用 ...
- [C++ Primer Plus] 第9章、内存模型和名称空间(一)程序清单
程序清单9.9(静态存储连续性.无链接性) #include<iostream> using namespace std; ; void strcount(const char *str) ...
- 《C++ Primer Plus 6th》读书笔记 - 第九章 内存模型和名称空间
1. 单独编译 1.1 头文件中常包含的内容: 函数原型 使用#define或const定义的符号常量 结构声明 类声明 模板声明 内联声明 1.2 只需将源代码文件加入到项目中,而不用加入头文件.这 ...
- C++学习 内存模型和名称空间
1.单独编译 C++鼓励程序员将组件函数放在独立的文件中,如果只修改了一个文件,则可以只重新编译该文件,然后将它与其他文件的编译版本链接. 一般非常有用的组织程序的策略是把程序分成三部分: 头文件:包 ...
- C++ Primer Plus读书笔记(九)内存模型和名称空间
1.作用域和链接 int num3; static int num4; int main() { } void func1() { static int num1; int num2; } 上边的代码 ...
- [C++ Primer Plus] 第9章、内存模型和名称空间(二)课后习题
一.复习题 2.using声明和using编译指令的区别 using声明: using std::cin; using std::cout; using std::endl; using编译指令:us ...
- python基础之函数对象,嵌套,名称空间和作用域
函数对象: 函数是第一类对象的含义是函数可以被当作数据处理 函数可用于: def func(): print(‘func’) 1.引用 f = func 把内存地址赋值给f 2.当作参数传给一个函 ...
随机推荐
- Linux系统结构 详解
Linux系统一般有4个主要部分: 内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用系统.部分层次结构如图1-1所 ...
- 使用 Gradle 快速创建 Java 项目
上一篇介绍了如何安装 Gradle,现在就可以直接通过已经安装好的 Gradle 创建一个普通 Java 项目 Gradle 默认内建了一个 init 插件,可以生成 Java 项目基础结构 $ gr ...
- “希希敬敬对”队软件工程第九次作业-beta冲刺第三次随笔
“希希敬敬对”队软件工程第九次作业-beta冲刺第三次随笔 队名: “希希敬敬对” 龙江腾(队长) 201810775001 杨希 201810812008 何敬 ...
- spring注解开发:Configuration&Bean
1.使用xml创建bean的方式 1.首先新建一个maven工程,添加如下依赖 <dependency> <groupId>org.springframework</gr ...
- python基本数据类型集合set操作
转:https://www.cnblogs.com/tina-python/p/5468495.html 一.集合的定义 set集合,是一个无序且不重复的元素集合. 集合对象是一组无序排列的可哈希的值 ...
- C++中初始化列表的使用
1,初始化列表是在 C++ 中才引入的: 2,以“类中是否可以定义 const 成员?”这个问题来引入初始化列表: 1,const 这个关键字可以定义真正意义上的常量,也可以在某些情况下定义只读变量: ...
- Add a system call on Ubuntu 13.04(x64) with x86_64
We added a system call to modify idt table, then programed it in modify_idt.c 1. Put our modify_idt. ...
- 【BZOJ2138】stone
题目 好厉害的题啊 这道题不难看成一个二分图模型,但是给人一种求最大匹配的感觉,这实在不是很好求的样子,于是自闭了 但是不妨这样来考虑,对于一个需求\(k_i\),我们求一个最大的\(x\leq k_ ...
- Visual Studio Code如何编写运行C、C++
Visual Studio Code如何编写运行C.C++ 作者:知乎用户链接:https://www.zhihu.com/question/30315894/answer/154979413来源:知 ...
- Ubuntu下安装chrome浏览器步骤
进入 Ubuntu 18.04 桌面,按下 Ctrl + Alt + t 键盘组合键,启动终端. 也可以按下 Win 键(或叫 Super 键),在 Dash 的搜索框中输入 terminal 或“终 ...