面向对象 C和C++知识点大全
面向对象:
对象:就是具有某类事务相同特征的 (数据和操作数据的方法)的集合
面向对象(Object Oriented) Object Oriented Programming,简称OOP,是一种程序设计思想。把(对象)作为程序的基本单元,一个对象包含了(数据和操作数据的方法)例如People{name,age,sex,function getSex(){ }}是一个people对象 类的(实例化)就是对象
⑴对象。 :对象是某类事物 抽象出来后 数据和方法的结合体,类的(实例化)
在面向对象程序设计中,对象所指的是计算机系统中的某一个成分。对象包含两个含义,其中一个是**(数据),另外一个是(操作数据的方法)。对象则是数据和方法的结合体。
它不仅能表示具体的事物,还能表示抽象的规则、计划或事件。
⑵对象的状态和行为。用数据描述状态,用操作数据的方法**描述行为。
对象具有属性,一个对象用数据值来描述它的属性。
对象还有行为,用于改变对象的状态,对象及其操作就是对象的行为。
对象实现了数据和操作的结合,使数据和操作封装于对象的统一体中
⑴.抽象 把某类事物具有相同的特性 { (数据)和(操作数据的方法) }抽离出来,就是抽象
抽某类事务出具有相同特性 { 属性(数据元素)和行为(功能) } 的对象,形成类
抽象级别:抽象主要包括 过程抽象 和 数据抽象
⑶类。
具有相同特性(数据元素)和行为(功能)的对象的抽象就是类。因此,对象的抽象是类,类的(实例化)就是对象,也可以说类的实例是对象(实例化一个对象),类实际上就是一种数据类型。
面向过程
把(计算机程序)视为一系列的命令集合,程序的基本单元,即一组函数的顺序执行
对类的概念
命令符:
* 取值运算符 & 寻址运算符 :: 域操作符(作用域操作符) -> 访问符号
- int p = &x; 对p赋值 操作的是指针变量的值所对应的地址
- :: 在类外部声明成员函数。void Point::Area(){};
调用全局函数;
表示引用成员函数变量及作用域,作用域成员运算符 例: System::Math::Sqrt() 相当于System.Math.Sqrt()
** :: //作用域 **
#include
using namespace std;
int avar=10; //全局变量avar
int main()
{
int avar=20; //局部变量avar
cout<<"avar is: "<<avar<<endl; // avar 访问局部变量
avar=25; //1 //修改局部变量
cout<<"avar is: "<<avar<<endl;
cout<<"avar is: "<<::avar<<endl; // ::ava 访问全局变量
::avar=30; //2 //修改全局变量
cout<<"avar is: "<<::avar<<endl;
return 0;
调用类的静态方法: 如:CDisplay::display(…)
** -> ** 访问符号 用于声明一个对象类型的指针 指向一个new 出来的这个对象
例:
Class Tv{
public int type;
public void changeVo(){} //对象就是类里面的变量
int math(void){
Tv *p = new Tv();
p->type = 0; //-> 访问符号
p ->changeVo()
}
}
int a=3; int &b=a; //b是a的引用(a引用了b),引用必经初始化,一旦初始化就不能改为指向其他对象
b = 10; 对b的操作也修改了a,对a的操作也修改了b。
- boolalpha 便是Cout<<输出的布尔型true/false 而不是0/1
count.width(n) n为整形,表示输出的数值的多少位
位运算符
赋值运算符
杂项运算符
C++ 数学运算
C++ 数据类型
C++ 日期 & 时间
有四个与时间相关的类型:clock_t、time_t、size_t 和 tm。类型 clock_t、size_t 和 time_t 能够把系统时间和日期表示为某种整数。
结构类型 tm 把日期和时间以 C 结构的形式保存,tm 结构的定义如下:
/* 输入日期判断是周几 /
例1:
#include <stdio.h> / printf, scanf /
#include <time.h> / time_t, struct tm, time, mktime /
int main ()
{
time_t rawtime;
struct tm * timeinfo;
int year, month ,day;
const char * weekday[] = { “周日”, “周一”,“周二”, “周三”,“周四”, “周五”, “周六”};
/ 用户输入日期 /
printf (“年: “); fflush(stdout); scanf (”%d”,&year);
printf (“月: “); fflush(stdout); scanf (”%d”,&month);
printf (“日: “); fflush(stdout); scanf (”%d”,&day);
/ 获取当前时间信息,并修改用户输入的输入信息 /
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
/ 调用 mktime: timeinfo->tm_wday */
mktime ( timeinfo );
printf (“那一天是:%s\n”, weekday[timeinfo->tm_wday]);
return 0;
让我们编译并运行上面的程序,这将产生以下结果:
年: 2018
月: 7
日: 26
那一天是:周四
例2:
#include
#include /* time_t, struct tm, time, mktime */
using namespace std;
int main( )
{
// 基于当前系统的当前日期/时间
time_t now = time(0);
cout << “1970 到目前经过秒数:” << now << endl;
tm *ltm = localtime(&now);
// 输出 tm 结构的各个组成部分
cout << "年: "<< 1900 + ltm->tm_year << endl;
cout << "月: "<< 1 + ltm->tm_mon<< endl;
cout << "日: "<< ltm->tm_mday << endl;
cout << "时间: "<< ltm->tm_hour << “:”;
cout << ltm->tm_min << “:”;
cout << ltm->tm_sec << endl;
}
当上面的代码被编译和执行时,它会产生下列结果:
1970 到目前时间:1503564157
年: 2017
月: 8
日: 24
时间: 16:42:37
C++ 随机数
随机数生成器有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。生成随机数之前必须先调用 srand() 函数。
j= rand();
cout <<"随机数: " << j << endl;
**
整数常量
**
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
头文件**#include **
头文件就是将别的文件里的代码插入到编程代码中的一种方式
iostream.h:用于控制台输入输出头文件。 //io stream的简写
fstream.h:用于文件操作的头文件。 //file stream的简写
complex.h:用于复数计算的头文件。
#include
#include //
命名空间 **using namespace std;**表示使用C++ 标准库
命名空间:实际上就是一个由程序设计者命名的内存区域,程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。
如: namespace ns1 //指定命名中间nsl
{ int a;
double b; }
namespace 是定义命名空间所必须写的关键字,nsl 是用户自己指定的命名空间的名字(可 以用任意的合法标识符,这里用ns1是因为ns是namespace的缩写,含义请楚),在花括号内是声明块,在其中声明的实体称为命名空间成员(namespace member)。现在命名空间成员包括变量a和b,注意a和b仍然是全局变量,仅仅是把它们隐藏在指定的命名空间中而已。如果在程序中要使用变量a和b,必须加上命名空间名和作用域分辨符“::”,如nsl::a,nsl::b。
using namespace std;
* 位运算(按位与、按位或、异或)
*** 按位与运算符(&)***只有两个数的二进制同时为1,结果才为1,否则为0。(负数按补码形式参加按位与运算)
运算规则:只有两个数的二进制同时为1,结果才为1,否则为0。(正数的补码跟反码规定就是自身(对它取反而得到反码不适用于正数),负数按补码形式参加按位与运算)
即 0 & 0= 0 ,0 & 1= 0,1 & 0= 0, 1 & 1= 1。
例:3 &5 即 00000011 & 00000101 = 00000001 ,所以 3 & 5的值为1。
*** 按位或运算符(|)*** 就是把前后两个数转换为二进制后,上下两个对应位只要有一个为 1,结果就为1异或运算符(^)
参加运算的两个数,按二进制位进行“异或”运算。
运算规则:参加运算的两个数,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
即 0 ^ 0=0 , 0 ^ 1= 1 , 1 ^ 0= 1 , 1 ^ 1= 0 。
例: 2 ^ 4 即 00000010 ^ 00000100 =00000110 ,所以 2 ^ 4 的值为6补码(负数来说,其反码为符号位保持不变,其余各位取反,其反码为符号位保持不变,其余各位取反后再在最后一位上加1。,最后一位结果满2的话往前进1) (正数的补码跟反码规定就是自身(对它取反而得到反码不适用于正数),负数按补码形式参加按位与运算)
例如:十进制数+18=二进制数010010(第一位为符号位,0为正,1为负),其反码和补码均为010010
十进制数-18=二进制数110010,其反码为101101(符号位保留,其余取反),补码为101110(符号位保留,其余各位取反后末位加1)
补码概念. 负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:
反码概念:(反码只是对负数来说的概念) (第一位符号位保留,其余取反),正数的反码规定就是 它自身(不能用取反方式计算)
引用类型:
1.结构体类型的引用:
#include<stdio.h>
int main()
{
struct node
{
int data;
int n;
}s1,s2,p; //s1 是结构体的名字
/
struct node1
{
int data;
int n;
}s2; //s2 是结构体的名字
*/
s1.data=1;
s1.n=10;
2指针类型的引用
*& 指针引用名等于指针
int main(void) //a,p,&q都是声明的int 类型的变量,不用看作取值,寻址
{
int a = 10;
int *p = &a; //指针p指向了a的地址 //引用 读作 指针p 指向地址a
int &q = p; //指针类型的引用q 指针()类型的引用(&q) 这样声明是因为后面还要对q进行赋值
*q = 20;count<<a<<endl; //a变成了20return 0;
{
3引用作为函数参数 既参数引用
C语言编写
void fun(int *a,int *b) //引用作为函数参数 a指针 b指针
{
int c= 0;
int c=*a ; //交换函数int *a=*b;*b =*c // &q = 20;count<<a<<endl; //a变成了20return 0;
{
int x=10,y=20;
fun(&x , &y); //引用&x和&y传递给函数的指针 取x的地址,y的地址
C++语言编写
void fun(int *a,int *b) //引用作为函数参数 a指针 b指针
{
int c= 0;
int c =a ; //交换函数int a=b;b =c
{
int x=10,y=20;
fun(x , y); //取x的地址,y的地址
**
C++ 指针 vs 数组
**
指针与数组
#include
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// 指针中的数组地址
ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << “var[” << i << "]的内存地址为 ";
cout << ptr << endl;
cout << “var[” << i << "] 的值为 ";
cout << *ptr << endl;
// 移动到下一个位置ptr++;
}
return 0;
}
指针数组
例1:
#include
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr[MAX]; //声明指针类型的数组ptr 其实跟声明变量是一样的
for (int i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; // 赋值为整数的地址 指针数组的di
}
for (int i = 0; i < MAX; i++)
{
cout << “Value of var[” << i << "] = ";
cout << *ptr[i] << endl;
}
return 0;
}
输出结果
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
例2:
#include
using namespace std;
const int MAX = 4;
int main ()
{
const char *names[MAX] = {
“Zara Ali”,
“Hina Ali”,
“Nuha Ali”,
“Sara Ali”,
};
for (int i = 0; i < MAX; i++)
{
cout << “Value of names[” << i << "] = ";
cout << names[i] << endl;
}
return 0;
}
输出结果为:
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
指向指针的指针(多级间接寻址)
#include
using namespace std;
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
// 获取 var 的地址
ptr = &var; //把 (地址var) 里面的值赋值给ptr
// 使用运算符 & 获取 ptr 的地址
pptr = &ptr; //把 (地址ptr) 里面的值赋值给pptr
// 使用 pptr 获取值
cout << “var 值为 :” << var << endl;
cout << “*ptr 值为:” << ptr << endl;
cout << “**pptr 值为:” << **pptr << endl; //相当于指针的传递 ((*pptr)) 相当于指向指针(*pptr) 而(*pptr)又指向指针(pptr)
return 0;
}
输出结果为:
var 值为 :3000
*ptr 值为:3000 //因为 *ptr 指向 地址var
**pptr 值为:3000 //因为 **pptr 指向 地址 *ptr
C++ 传递指针给函数
例1:
#include
#include
using namespace std;
void getSeconds(unsigned long *par);
void getSeconds(unsigned long *par)
{
// 获取当前的秒数
*par = time( NULL );
return;
}
int main ()
{
unsigned long sec;
getSeconds( &sec );
// 输出实际值
cout << “Number of seconds :” << sec << endl;
return 0;
}
输出结果为:
Number of seconds :1294450468
例2:
#include
using namespace std;
// 函数声明
double getAverage(int *arr, int size);
double getAverage(int *arr, int size)//*arr指向了int main ()主函数中的 int //balance[5]数组
{
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i)
{
sum += arr[i];
}
avg = double(sum) / size;
return avg;
}
int main ()
{
// 带有 5 个元素的整型数组
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
// 传递一个指向数组的指针作为参数
avg = getAverage( balance, 5 ) ;
// 输出返回值
cout << "Average value is: " << avg << endl;
return 0;
}
输出的结果:为数组的平均数
Average value is: 214.4
Const常量与基本数据类型
Const与指针
1、指针所指向的内容是常量不可变
const int *p = null;
int const *p = null;
2、指针本身是常量不可变
(int*) const p = null;
const (int*) p = null;
3、 两者都不可变
const int* const p=null;
5、const修饰函数参数
const修饰函数参数是它最广泛的一种用途,它表示函数体中不能修改参数的值(包括参数本身的值或者参数其中包含的值)。它可以很好
void function(const int Var); //传递过来的参数在函数内不可以改变(无意义,因为Var本身就是形参)
void function(const char* Var); //参数指针所指{(内容为常量不可变)}
void function(char* const Var); //参数{(指针本身)为常量不可变}(也无意义, 因为char* Var也是形参)
参数为引用,为了增加效率同时防止修改。
Const与引用 修饰引用参数时:
void function(const Class& Var);//引用参数在函数内不可以改变
void function(const TYPE& Var); //引用参数在函数内为常量不可变
Const与函数(主要是参数)
7、const 修饰函数返回值
const修饰函数返回值其实用的并不是很多,它的含义和const修饰普通变量以及指针的含义基本相同。
(1) const int fun1() 这个其实无意义,因为参数返回本身就是赋值。
(2) const int * fun2()
8、调用时 const int *
函数
在创建函数时,必须编写其定义。所有函数定义包括以下组成部分:
• 名称:每个函数都必须有一个名称。通常,适用于变量名称的规则同样也适用于函数名称。
• 形参列表:调用函数的程序模块可以向其发送数据。形参列表是保存传递给函数的值的变量列表。如果没有值传递给函数,则其形参列表为空。
• 主体:函数的主体是处理函数正在执行的任务的一组语句。这些语句包含在一组大括号中。
• 返回类型:函数可以将值发送回调用它的程序模块。返回类型是要发送回的值的数据类型。
并不是所有函数都一定要返回值,该函数的返回类型是 void。这意味着函数在完成执行后不返回值,因为没有返回值,所以不需要 return 语句
void displayMessage()
{
cout << “Hello from the function displayMessage.\n”;
}
1可以给函数参数设置默认值:
2重载:
函数名相同,参数列表不同,需要多次声明,(下文中对函数来说有介绍)
3内联函数
inline 关键字
增加了 inline 关键字的函数称为“内联函数”。增加了 inline 关键字的函数称为“内联函数”。内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,不会将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处,就像整个函数体在调用处被重写了一遍一样。
内联函数会使最终可执行程序的体积增加。以时间换取空间,或增加空间消耗来节省时间
1内联函数是建议性的,有编译器决定
2需求逻辑简单(不能加for,while,switch)
3递归函数,无法使用内联方式
4不能进行异常数据声明
inline int Max (int a, int b) //声明
{
if(a >b)
return a;
return b;
}
内存管理
I、栈区
1、在函数中,函数的局部变量的存储单元在栈上,函数执行结束后栈区自动释放。
2、栈内存分配效率高,由操作系统和编译器自动分配,但存储空间有限。
II、堆区
1、堆区中的内存由程序员自己创建并维护,每个new都应该对应于一个delete,如果程序员忘记释放堆内存,则在程序最后结束后会由操作系统完成释放,但在程序运行过程中可能会造成堆区越来越大,从而造成内存溢出。
c#中
值类型:(基本数据类型(如:int,float,bool等) , (结构体,枚举,空类型)
存放在栈上
引用类型: 自定义的 (类,接口,委托),( 数组,字符串,Object)
存放到堆上
运算符:{new 申请内存 delete释放 int *arr = new int[10] }
方式: {int *p = new int}
释放: {delete p; delete []arr }
注意
1 申请失败(计算机没有足够的内存)
int *p = new int[100];
if(Null = p){
//内存分派失败
}
delete:
*p = Null //指针设置为空,避免再次释放p。 delete p 出现异常
成员函数包括
一般成员函数:
属性成员函数:
特殊函数:{ 构造函数, 析构函数 }
字符串数组操作函数*
str3 的总长度
len = str3.size();
strlen 求字符串的有效字符数 不包含’\0’ 返回值为无符号类型
strcpy 字符串复制
strncpy 字符串部分复制
strcat 字符串追加 把某个字符串传递到某个字符串的末尾
strcmp 比较字符串:比较字符内容(数值/ascii值)
strchr 在字符串中找字符 如果找到返回该字符的所在串中地址,
如果有多个则返回第一个的地址 如果没找到则返回NULL
strstr 在字符串中找子串 如果找到返回该子串的所在串中地址,如果没找到则返字符串分割
strtok char *strtok(char *str, const char *delim) 不可重入函数
strsep char *strsep(char **stringp, const char *delim) 可重入函数
atoi 将数字字符串转换为整数 atol atof 数字字符串转化为整数
memset void *memset(void *s,int c,size_t n); 将s开始的n个字节的内存空间的每个字节设置为c值
memcpy void *memcpy(void *dest,const void *src,size_t n) 不可处理重叠区域
memmove void *memmove(void *dest,const void *src,size_t n); 内存复制 C唯一可处理重叠区域的函数
常规操作:
s.empty() //若为空,返回true 否者返回false
s.size() //返回s中字符串的个数
s[n] //返回s中位置为 n 的字符(从0开始)
string s2 = “hello” + ”world“; //这句是错误的 不能直接相加两个值
string s1 = “start” string s2 = “hello” + s1 + ”world“;这两句是对的 两个值不可以直接相加,中间可以加一个变量
条件编译指令:
#define 预处理器
#define 定义一个预处理宏
#undef 取消宏的定义
例:
#ifndef ABCD_H
#define ABCD_H
// … some declaration codes
#endif // #ifndef ABCD_H
#ifndef 表示”如果“ ” no没有“ ”define定义某个 “标记符 就执行下面的语句
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef 与#ifdef相反,判断某个宏是否未被定义,若未定义,执行随后的语句
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined 与#if, #elif配合使用,判断某个宏是否被定义
#ifdef _DEBUG
例:
// … do some operations
#endif
#ifdef _WIN32
// … use Win32 API
#endif
sizeof(类型名) 该类所占的字节数
sizeof + 表达式 结果所占字节数
sizeof + 变量命 该变量的类型所占的字节数
属性封装([ 数据(就包括构造函数,) ] / 字段封装)
二、字段、属性 一般一个类中是(字段+属性 或者 字段+构造函数)的结构
class Person
{
int age ;//字段(就是普通的变量)在C++里面又叫对象
int Age //属性(本质是一个函数 ,用来对字段操作)
{
get{return age;}
set { age=value; }
}
三、构造函数
C++提供了构造函数(constructor)来处理对象的初始化。而是在建立对象时自动执行。
class Person
{
int age ;//字段(就是普通的变量) 在C++里面又叫对象
public Person() //本质是一个函数,但是没有返回值,名字就是类名, 用以初始化对象,即对字段做赋值操作,,注意与属性对比 他们的异同
{
age=10;
}
拷贝构造函数:
普通构造函数在程序中(建立对象)时被调用。 复制构造函数在 (用已有对象复制一个新对象)时被调用,在以下3 种情况下需要克隆对象
例如 创建对象A a01(“david”,19);
再次创建对象时,A a02=a01; A a02(a01);//这些格式都属于拷贝构造函数
复制构造函数与构造函数的不同之处在于形参,复制构造函数student的形参是对student构造函数的引用,其功能是将一个对象的每一个成员num,math复制到另一个对象对应的成员当中。
存在唯一的参数 对对象的引用
拷贝构造函数作用:实现对象初始化对象
浅拷贝与深拷贝
默认的拷贝构造函数实现的只能是浅拷贝,即直接将原对象的数据成员值依次复制给新对象中对应的数据成员,并没有为新对象另外分配内存资源。
这样,如果对象的数据成员是指针,两个指针对象实际上指向的是同一块内存空间。
在某些情况下,浅拷贝回带来数据安全方面的隐患。
当类的数据成员中有指针类型时,我们就必须定义一个特定的拷贝构造函数,该拷贝构造函数不仅可以实现原对象和新对象之间数据成员的拷贝,而且可以为新的对象分配单独的内存资源,这就是深拷贝构造函数。
深拷贝构造函数(指针构造函数)
当数据成员中有指针时,必须要用深拷贝。
但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。所以,这时,必须采用深拷贝。
#include
#include
using namespace std;
class Test
{
private:
int a;
char *str;
public:
Test(int b, char *s)
{
a=b;
strcpy(str , s); //肇事地点,但不是祸端 字符串粘贴函数,把变量 *str字符串 和 和Test的参数 *s字符串 进行粘贴
}
Test(const Test& C)
{
a=C.a;
strcpy(str , C.str); //字符串粘贴函数,把 *str 和 s 进行粘贴
}
void show ()
{
cout<<a<<“,”<<str<<endl;
}
};
int main()
{
Test a(100,“hello”); //普通函数
Test b(a); //调用深度(指针)构造函数 b(a),
a.show(); //构造函数a 调用Show方法显示Cout<< ,
b.show(); //构造函数b 调用Show方法显示Cout<<,
return 0;
四 析构函数
当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间。
int age;
int level;
char * arr;
Person(int age, int level) {
this->age = age;
this->level = level;
arr = (char *)
malloc(1024);
}
~Person() { //析构函数 和类名相同,且带波浪号
free(arr);
printf(" 析构函数调用打印\n");
}
内存分区
栈: 内存由系统控制,无需程序员控制
堆: 需要程序员控制
全局区: 存储全局变量和金,
**常量区:**存储常量
代码区: 存储编译为翻译为二进制的代码
,
**
C++ 存储类
**
register 存储类
register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)。
{
register int miles;
}
static 存储类
static 指示编译器在程序的生命周期内保持局部变量 的存在,
static 修饰符也可以应用于全局变量。当 static 修饰全局变量 时,会使变量的作用域 “限制” 在声明它的文件内。
extern 存储类
extern 存储类用于提供一个全局变量的引用 ,全局变量对所有的程序文件都是可见的。当您使用 ‘extern’ 时,对于无法初始化的变量,会把变量名 “指向”一个之前定义过的~~存储位置。~~
第一个文件:main.cpp
实例
#include
int count ;
extern void write_extern();
int main()
{
count = 5;
write_extern();
}
第二个文件:support.cpp
实例
#include
extern int count; //无法初始化的变量,会把变量名指向一个之前定义过的存储位置mian函数的count中,类似JS,TS中import export 于函数与函数之间的变量引用
void write_extern(void)
{
std::cout << "Count is " << count << std::endl;
}
在这里,第二个文件中的 extern 关键字用于声明已经在第一个文件 main.cpp 中定义的 count。现在 ,编译这两个文件,如下所示:
$ g++ main.cpp support.cpp -o write
这会产生 write 可执行程序,尝试执行 write,它会产生下列结果:
$ ./write
Count is 5
mutable 存储类
mutable 说明符仅适用于类的对象,这将在本教程的最后进行讲解。它允许对象的成员替代常量。也就是说,mutable 成员可以通过 const 成员函数修改。
thread_local 存储类
使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。
thread_local 说明符可以与 static 或 extern 合并。
thread_local int x; // 命名空间下的全局变量
class X
{
static thread_local std::string s; // 类的static成员变量
};
static thread_local std::string X:
面向对象 C和C++知识点大全相关推荐
- python基础知识点大全
python基础知识点大全 Excerpt 什么是CPython?编译型与解释型编程语言一般认为,Python与Java都是解释型语言,只是不那么纯粹.也可以认为它们是先编译再解释的编程语言.并非所有 ...
- 两个数相乘积一定比每个因数都大_小升初数学知识点大全含公式+20类必考应用题(含答案解析),孩子考试一定用得上!...
小升初数学知识点大全含公式 一.几何图形周长.面积和体积公式* 三角形的面积=底×高÷2.S= a×h÷2 正方形的面积=边长×边长 S= a² 长方形的面积=长×宽 公式 S= a×b 平行四边形的 ...
- 前端面试知识点大全——浏览器篇
总纲:前端面试知识点大全 目录 1.浏览器工作原理 2.浏览器如何解析css,如何渲染css的 2.1 构建DOM树 2.2 构建CSSOM规则树(就是css规则树) 2.3 渲染阻塞 2.4 构建渲 ...
- c语言二级考试知识点,2016年计算机二级考试C语言知识点大全
2016年计算机二级考试C语言知识点大全 第一章 1)合法的用户标识符考查: 合法的要求是由字母,数字,下划线组成.有其它元素就错了. 并且第一个必须为字母或则是下划线.第一个为数字就错了. 关键字不 ...
- 计算机表格函数知识点,Excel知识点大全
<Excel知识点大全>由会员分享,可在线阅读,更多相关<Excel知识点大全(29页珍藏版)>请在人人文库网上搜索. 1.实用标准文档必修:excel上机考试知识点一.数据的 ...
- 计算机三级网络技术知识点大全(七)
无线局域网设别安装与调试 1.常用的无线局域网标准主要包括:蓝牙标准.HiperLAN标准和IEEE802.11标准. 2.因为蓝牙技术可以方便地嵌入到单一的CMOS芯片中,因此它特别适用于小型的移动 ...
- 计算机三级网络技术知识点大全(二)
1.基于网络的信息系统主要包括以下几个部分:网络运行环境.网络系统.网络操作系统.网络应用软件开发与运行环境.网络应用系统.网络安全系统和网络管理系统. 2.网络运行环境包括机房和电源两部分. 3.网 ...
- 计算机三级网络技术知识点大全(一)
1.按覆盖的地理范围划分,计算机网络可以分为局域网.城域网和广域网. 2.局域网提供高数据传输速率10Mbps-10Gbps,低误码率的高质量数据传输环境. 3.从介质访问控制方法划分,局域网可以分为 ...
- c语言中swith的用法,初中英语语法知识点大全+记忆口诀+易错题100道,考前复习...
原标题:初中英语语法知识点大全+记忆口诀+易错题100道,考前复习 初中英语语法知识点大全 初中英语记忆口诀 1.be的用法口诀 我用am,你用are,is连着他,她,它: 单数名词用is,复数名词全 ...
最新文章
- 重学C语言_数据结构与基础语法
- docker快速搭建RabbitMQ集群
- spring mvc学习(17)Intellij IDEA创建maven项目无java文件问题
- Java基础--反射
- hive2 java连接_用Java代码通过JDBC连接Hiveserver2
- 漫步微积分三十八——流体静力学
- 上传文件到服务器地址怎么配置,文件上传到服务器怎么配置
- 记录一下所了解的一些第三开源框架
- List的ToLookup 分组方法
- 银行客户用户画像_大数据精准营销用户画像是核心-金融业大数据用户画像实践...
- 微信小程序的支付流程 —— 总结
- 如何对客户行为进行数据分析?
- c语言项目实战 —— 图书管理系统
- 数论读书笔记——欧几里得和扩展欧几里得
- 卡通渲染技巧(一)——漫反射部分
- js实现放大镜(详细注释)
- 《Gans in Action》第三章 用GAN生成手写数字
- ipv6默认网关怎么打开。有偿。
- 构建智慧城市管理体系,京东方智慧物联平台赋能细分场景
- linux平台性能监控系统,如何使用top命令监控Linux系统性能