嵌入式笔记24 命名空间 输入和输出 C++对C的升级
文章目录
- C++特点
- 一、命名空间
- 命名冲突的解决
- C语言中
- C++中命名冲突的解决:命名空间
- 命名空间的定义
- 命名空间的使用
- 以下情况
- 防止头文件重复的两种方法
- std的介绍和使用
- 命名空间注意事项
- 二、输入与输出
- printf、cout缓冲区问题
- printf
- cout
- cin输入
- 缓冲区垃圾问题
- cerr错误流
- 重定向
- 三、C++对C的升级
- 基本语句的升级
- for语句
- 关键字的升级register
- 程序的存储位置
- C中register的使用
- 作用
- 语法作用
- 使用注意事项
- 什么时候用register修饰一个变量
- volatile
- 作用
- 使用场景
- C++中对register的升级
- 优化内容
- 关键字的升级auto
- C语言中
- C++中
- 关键字的升级typedef
- C中typedef作用
- typedef工程应用作用
- 函数名命名规则
- typedef存在的问题
- C++中typedef的升级 typedef==using
- 关键字const优化
- C中const作用
- 什么是只读
- 工程应用的作用
- C++中const的升级
- 优化内容
- constexpr
- C++对C的升级:类型的升级
- 引入bool类型
- 三目运算符的升级
- C语言中
- C++语言中
- 引用
- C语言中
- C++语言中
- 引用作用
- 语法作用
- 注意事项
- 作用场景
- 引用是否占用额外的内存空间?
- 左值、右值引用
- 左值
- 左值引用
- 右值
- 右值引用
- eg:判断左值还是右值
- eg:引用
- 左值转换成右值
- eg
- malloc/free升级,引入new、delete
- malloc、free
- new、delete
- malloc free vs new delete
- 关于多维数组的分配
- 规则多维数组
- 不规则的多维数组
- NULL升级
- C++中nullptr
- 函数的升级
C++特点
封装、继承、多态
一、命名空间
命名冲突的解决
C语言中
1、c语言中解决命名冲突的方法:使用static关键字
- 作用:
修饰局部变量:延长局部变量的生命周期,程序结束后再释放
修饰全局变量:该全局变量只能在本文件访问,不能在其他文件访问
修饰函数:该函数只能在本文件调用,不能在其他文件调用
#include <iostream>int count = 4;int count = 5;
int main()
{return 0;
}
报错出现重复定义
C++中命名冲突的解决:命名空间
命名空间的定义
namespace 名字{变量、函数}
命名空间的使用
1、使用作用域限定符:使用命名空间的名字::变量名或者函数名
2、使用using关键字导入命名空间:using namespace 命名空间;using 命名空间::变量名或者函数名
eg:
#include <iostream>
namespace myspcaeA//解决命名冲突问题
{int count = 4;int index = 0;
}namespace myspaceB
{ int count = 5;int index = 10;
}
int count = 6;//默认全局的变量
int index = 20;
int main()
{printf("count = %d\n",count);//默认输出全局变量,输出6printf(“count = %d\n”,myspaceA::count);printf(“count = %d\n”,myspaceB::count);printf("count = %d\n",index);//默认输出全局变量,输出6printf(“count = %d\n”,myspaceA::index);printf(“count = %d\n”,myspaceB::index);return 0;
}
想要输出myspaceA里面的内容
引入运算符: ::作用域限定符
namespace myspaceB
{ int count = 5;int index = 10;namespace myspaceBB//可以嵌套使用{int count = 7;}}printf(“count = %d\n”,myspaceB::myspaceBB::count);//输出格式
//访问myspaceC中的数
namespace myspaceC
{int max = 10;int min = 10;
}using namespace myspaceC;//将myspaceC导成全局变量
//using namespace myspaceA;
//using namespace myspaceB;//尽量少用using 导入命名空间,因为会导致命名冲突
//输出的话会再次出现命名冲突
printf("max = %d\n", max);//输出格式
以下情况
1、不同源文件可以有相同的命名空间
2、使用命名空间加作用域限定符访问成员时,优先导入本文件的命名空间
3、使用using导入命名空间时,导入的是所以程序中的命名空间(只要没有命名冲突都是被允许的)(直接导入)
防止头文件重复的两种方法
命名空间尽量定义在.h文件
//防止头文件重复包含的两种方法
//1、用宏
//2、#pragm once 预处理指令,z只编译一次(大部分使用)
//#ifndef __NAMESPACE_H_
//#define __NAMESPACE_H_//宏
#pragm once //预处理指令,z只编译一次
.
.
.
//#endif
std的介绍和使用
#include <iostrenm>
//std:包含升级之后的功能
int main()
{ std::cout << "hello world" << tsd::endl;//std:标准库命名空间
}
//简化
#include<iostream>
using namespace std;//此命名空间存放的是C++相对于C升级的功能(函数、库文件、变量)
int main()
{cout << "hello world" << endl;
}
命名空间注意事项
(1)不能访问其他源文件的命名空间
(2)当多个源文件的命名空间名字相同时:如果没有出现重复的变量名或者函数命名,系统会合并两个命名空间(但是实际上并不是合成一个命名空间,只是能通过编译);否则会报错
二、输入与输出
#include<iostream>using namespace std;int main()
{//cout printf 缓冲区const char *ptr = "hello world";char temp = 'X';int num = 6;double b = 1.342;cout << "hello world" << endl;cout << "ptr =" << ptr << endl;cout << "temp = " << temp << endl;cout << "num = " << num << endl;cout << "b = " << b << endl;cout << " &num = "<< &num << endl;printf("ptr = %p\n", ptr);}
printf、cout缓冲区问题
printf
/*不能输出*/
#include <stdio.h>int main()
{printf("hello world!");//scanf//flush;刷新缓冲区//while(1);也能输出,每次程序执行完后,清空缓冲区return 0;
}
printf:行缓冲:满一行输出或遇到‘\n’
使用printf调试时,一定要加’\n’或手动刷新缓冲区
scanf:输入前,刷新缓冲区
cout
#include <iostream>using namespace std;int main()
{cout << "hello worlld!" << endl;// cout << "hello worlld!\n" //endl相当于刷新,输入'\n'while(1);return 0;
}
cin输入
#include <iostream>using namespace std;
int main()
{int num;char str[100];double b;// //cin :输入流 cunt:输出流 cerr 错物流 clog 日志流 对象//流运算符: >>输入 <<输出cout << "Please input num:";cin >> num;//getchar();cin.get();cout << "Please input str:";//cin >> str;cin.getline(str,100);//getline()cout << "Please input b:";cin >> b;cout << num << endl;cout << str << endl;cout << b << endl;
}
输入垃圾问题
缓冲区垃圾问题
getchar();
cin.get();
cerr错误流
#include <iostream>using namespace std;
int main()
{cerr << "hello world!" << endl;//dup dup2重定向到文件或某个远程socket里//cerr没有缓冲区clog << "hello world!" << endl;//clog有缓冲区return 0;
}
重定向
#include <stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>int main()
{//0标准输入 1标准输出 2标准出错int fd = open ("hello.txt", O_RDWR | O_CREAT, 0655);dup2(fd, STDOUT_FILENO);//输出重定向到fd上dup2(fd, STDIN_FILENO);//输入重定向 从文件里面读 dup2(fd, STDERR_FILENO);//错误信息重定向到fd//sockfd = socket confd;//dup2(STDOUT_FILENO,cond);char src[100];read(STDIN_FILENO, src, sizeof(src));//从键盘上读printf("src = %s\n",src);write(STDERR_FILENO, "hello world", 11);//输出到终端上return 0;}
#include <iostream>
#include<stdio.h>
using namespace std;//标准库命名空间int main()
{int num;char ch;//输入垃圾问题printf("Please input num:\n");scanf("%d",&num);getchar();printf("Please input ch:\n");scanf("%c",&ch);//cin :输入流 cunt:输出流 cerr 错物流 clog 日志流 对象//流运算符: >>输入 <<输出cout << "hello world" << endl;cout << "num = " <<num<< endl;cout << "num = " << ch << endl;printf("num = %d ch = %s\n",num,ch);
}
三、C++对C的升级
基本语句的升级
for语句
优化循环变量的作用域
#include <stdio.h>
int main()
{int i;
for(i = 0; i<=100; i++)
{}
//只有for循环结束后空间才能释放,浪费资源
return 0;
}
#include<iostream>using namespace std;int main()
{for(int i = 0; i < 100; i++) //节省空间,在C语言中也支持{}//freachint array[5] = {1,2,3,4,5} ;for(int temp : array){ cout << temp << endl;}char src[100] = "hello world";for(char temp : src){if(temp != '\0'){cout << temp << endl;}else{break;}}return 0;
}
条件表达式:可以做左值
关键字的升级register
程序的存储位置
C中register的使用
作用
提高程序运行效率(省去CPU从内存抓取数据的开销)
语法作用
尽可能将变量保存在CPU内部寄存器中
使用注意事项
1、只能修饰局部,不能修饰全局变量和函数
2、register修饰变量,不能通过&获取该变量的地址(有可能该变量保存在CPU内部寄存器中,&获取的是内存里的)
3、register修饰变量类型一定是CPU所能处理的数据类型(有的CPU不支持浮点型运算)
什么时候用register修饰一个变量
频繁访问的变量
volatile
作用
防止编译器优化(将变量优化到寄存器中(寄存器存在边际效应))
使用场景
访问硬件时,所使用的全局变量
volatile int count = 5;
volatile register int index;//提醒检查寄存器的变量是否有变化
C++中对register的升级
优化内容
当对register变量取地址时,会将该变量重新保存到内存中
#include<iosteram>using namespace std;
int main()
{register int num = 5;printf("&num = %p\n",&num);return 0;
}
const关键字的升级:const修饰的是变量
地址之间的赋值必须是const对const
const:修饰变量、只读变量
const int num = 5;const int *p_num = &num ;
关键字的升级auto
C语言中
自动变量,离开作用域时自动释放
只是用来说明该变量的作用域,相当于局部变量
C++中
auto变量:类型推导,实现高效编程
#include<iosteram>using namespace std;
int main()
{int num = 5;const char *ptr = "hello world";auto num1 = 5;//根据所赋值推导数据类型auto ptr1 = "hello world";int array[5] = {1,2,3,4,5} ;for(auto temp : array){ cout << temp << endl;}vector<int> v = {1,2,3,4,5};//vector<int>::iterate it;for(auto it = v.begin(); it = v.end(); it++){cout << *it << endl;}return 0;
}
auto ch1 = ‘a’;//
string s1 = “hello”;
string ::iterator it = s1.begin();
auto it2 = s1.begin();
关键字的升级typedef
C中typedef作用
typedef关键字的作用:给数据类型重命名
typedef工程应用作用
1、提高代码可读性
2、提高移植性
函数名命名规则
解决的是函数功能的可读性,无法解决形参的可读性
//提高代码的可读性
typedef int name_len;
int func(name_len a);//解释形参a的意思typedef unsigned int Int;
Int num;
//想改int的类型
重命名:
pid_t pid;
size_t size;
mode_t mode;
off_t f;
typedef存在的问题
重命名函数指针时,可读性差
int add(int a,int b)
{return a+b;
}
int main()
{ typedef int (*P_FUNC)(int,int);//typedef int(*)(int,int) P_FUNC;int (*p_add)(int,int);//p_add函数指针变量P_FUNC p_add = add;//初始化p_add(5,6);//调用return 0;
}
C++中typedef的升级 typedef==using
using重命名
using关键的升级:替代C语言typedef的关键字
#include <iostream>
using namespace std;
int add(int a,int b)
{return a+b;
}
int main()
{ using P_FUNC = int (*)(int,int);using Int = int;Int aa = 5;P_FUNC p_add = add;cout << p_add(5,6) << endl;return 0;
}
using Int = int;//typedef int Int;
using Len = int;// typedef int Len;
using P_FUNC = int (*)(int,int);typedef
Int c;//int c;
Len c2;
add(6,5);
P_FUNC p_func;//int (*p_func)(int,int) = add;
p_func(6,5);
关键字const优化
C中const作用
将一个变量变为只读变量
什么是只读
const int num = 5;
int *p = & num;
*p = 7;
printf("num = %d\n",p);//还是会输出7,但是会报警告
int num = 5;
const int *p = & num;int const *p = #//还是*p不可变
int * const p = #//是p不可变
*p = 7;
p++;//1
*p++;//2
num++;//3
//1、3可变printf("num = %d\n",p);
工程应用的作用
修饰函数形参,保护实参在函数运行过程中不被改变
C++中const的升级
优化内容
const修饰的变量是常量
#include<iostream>
using namespace std;
int main()
{int num = 5;
const int *p = #
cout << num << endl;
return 0;
}
constexpr
constexpr替换宏 #define
constexpr int getNum()
{return 5;
}
#define MAX(a,b) a>b?a:b //傻瓜式替换 无法定义复杂的函数(不检查语法错误)
constexpr int cout = 5;//相当于宏定义,检查语法错误//这里count就是常数5,不可变
cout++;//报错
C++对C的升级:类型的升级
引入bool类型
bool is_null = true;
bool is_null = flase;
三目运算符的升级
C语言中
int a = 5;
int b = 6;
(a>b?a:b) = 9;//报错,不可以这样赋值
C++语言中
1、结果可以作为左值
int a = 5;
int b = 6;
(a>b?a:b) = 9;//不报错,输出5,9
//while(a>b,a<b)支持,表达式
引用
C语言中
#include<stdio.h>
/*void swap(int a,int b)
{int temp;temp = a;a=b;b=temp;
}*/
void swap(int *a,int *b)
{int temp;temp = *a;*a=*b;*b=temp;
}
void func(char **ptr)
{(*ptr)++;
]
char * func2()//不要返回局部变量的地址或者指针
{static char src[100] = "heoll world";return src;
}
int main()
{int a =5;int b = 6;//swap( a,b);//实参变量名swap(&a,&b);//什么时候传地址,什么时候传值//当修改实参变量值时,传实参变量的地址(传实参变量的地址,既可以使用也可以修改实参变量的值)//当只使用不修改变量值时,传实参变量名(传实参变量名只能使用实参变量的值,不能修改)printf("a = %d,b = %d\n",a,b);char *ptr = "hello world";func(ptr);//传的是实参变量名func(&ptr);//实参变量地址printf("ptr = %s\n",ptr);char *result = func2();printf("result = %s\n",result);//返回result = (null)return 0;
}
C++语言中
引用作用
解决的是函数指针传参和返回值问题
语法作用
引用就是给变量起别名,操作引用相当于在操作引用所绑定的变量
#include<iostream>
using namespace std;
int main()
{int count = 5;int &r_count = count;r_count++;count++;cout << count << endl;//两者相互影响,改变其中一个,另一个也改变cout << r_count << endl;
}
注意事项
1、定义引用必须绑定变量(定义引用必须初始化,不能定义空引用)
2、一旦绑定就不能再次绑定到其他变量上
注:常引用:const修饰的引用,绑定常量
/*引用的作用:函数的形参和返回值*/
#include<iostream>
using namespace std;
void swap(int &a,int &b)//引用作为函数形参:传值和传地址问题
{int temp = a;a = b;b = temp;//实参和形参绑定
}
void test(const int &a)//a:常引用:只能使用不能修改其绑定的值
{}void & getNum(int a)//引用作为函数返回值
{static int temp = a + 1;return temp;
}
int main()
{int a = 5;int b = 6;swap(a,b);printf("a = %d b = %d\n",a,b);//两者交换getNum(a) = 5;//函数调用做返回值:修改返回的值//getNum(a);输出结果为7cout << getNum(a) << endl;
}
作用场景
作为函数的形参,作为函数的返回值(函数的调用可以做左值)
int left = 5;
int right = 6;
swap(&left,*right);
count <<left << " "<< right;void swap(int *left , int *right)
{int temp;temp = *left;*left = *right;*right = temp;
}
int temp = test();
test() = 10;//修改num的值
int left = 5;
int right = 6;
int &l_left = left;
cout << left << endl;
swap(&left,*right);
count <<left << " "<< right;
int const = 5;
int &
int func (const int &num1,const int num2)
{
}
void swap(int &left , int &right)
{
int temp;
temp = left;
*left = *right;
*right = temp;
}
int & test()
{
static int num = 5;
cout << num << endl;
return num;
}
引用是否占用额外的内存空间?
引用占用内存空间
编译器优化:不将这个空间展示给开发人员,不能操作这段空间“新的数据类型”
#include<iostream>
using namespace std;
struct node
{int n;int &rn;
};
int main()
{cout << sizeof(struct node) << endl;//输出占用16字节
}
左值、右值引用
C++11:左值引用、右值引用
左值
可以被修改的值可以作为左值(可以取地址的可以作为左值)
左值引用
只能绑定左值 int &
右值
不可以被修改的值可以作为右值(不可以取地址的可以作为右值)
右值引用
只能绑定右值 int &&(对象移动)
eg:判断左值还是右值
int num = 5;//num是左值,5是右值
int *p = #//&num是左值还是右值
(&num)++;//报错,不能加加,所以&num是右值
eg:引用
void func1(int &l_num)//左值引用作形参
{cout << l_num << endl;
}
void func2(int &&r_num)
{cout << r_num << endl;
}
int main()
{int num = 5;
int &l_num = num;
int &&r_num = 5;//移动构造函数,移动拷贝赋值运算符的重载
r_num++;//不报错,所有它是2左值
//int &&r_num1 = r_num;//报错
func1(num);
func1(l_num);//l_num++
//func1(5);//报错,单纯的左值引用不可以绑定常量
//上面函数改成 void func1(const int &l_num){}就可以
func2(5);
//func2(r_num);//报错,左对左,右对右,r_num是个左值
func2(std::move(r_num));//将左值转换成右值
func1(r_num);
return 0;
}
左值转换成右值
std::move();
eg
func2(std::move(r_num));//将左值转换成右值
作业
引用是不是数据类型?(不是)它占不占用内存空间(运行时不占用内存空间, 编辑时预留内存空间!!!!)
指针和引用的区别
什么是对象移动?对象移动的作用?
malloc/free升级,引入new、delete
malloc、free
#include<stdio.h>
#include<stdlib.h>
int main()
{//void * malloc(size_t size);分配的空间大小//void free(void *adrr);释放的空间地址char *ptr = (char *)malloc(sizeof(char) * 100);//指针赋值一定是相同类型int *p_arr = (int *)malloc(sizeof(char) * 100);//400字节(4*100)按字节分配if(ptr == NULL){perror("malloc error!");exit(1);}memset(ptr,0,sizeof(char) * 100);//设初值strcpy(ptr,"hello world!");//拷贝字符串free(ptr);//free函数如何知道要释放多少内存空间?ptr = NULL;return 0;
}
new、delete
#include<iostream>
using namespace std;int main()
{/*分配的同时初始化*/char *p = new char('a');//分配一个字节cout << *p << endl;//输出a//按类型个数分配char *ptr = new char[100];delete p;//释放delete [] ptr;// char *ptr = new char[100]{"hello world"};不支持//int *p_arr = new int[10]{1,2,3,4};//支持/*for(i=0;i<10;i++){cout << p_arr[i] << endl;//没有输出}*///分配二维数组int (*p)[5]=new int[4][5];char (*ptr)[100] = new char[3][100];int **array2;//适合分配不规则的多维数组array2 = new int *[2];for(int i = 0;i<2;i++){array2[i]=new int[3];}//分配三维数组int (*p)[2][100] = new int[3][2][100];return 0;
}
malloc free vs new delete
1、new、delete(暂时)理解为运算符 malloc、free是函数
2、new、delete按照类型的个数为单位 malloc、free按照字节为单位分配
3、new、delete:可以初始化 malloc、free只能手动初始化
(关于初始化:最好手动初始化 默认初始化都是0)
4、new、delete:如果分配失败会产生异常, malloc、free:返回NULL
5、new底层调用的是malloc delete底层调用还是free
6、new、delete:频繁分配小内存会导致内存产生碎片,同时会增加开销(系统) 池化技术:内存池
关于多维数组的分配
规则多维数组
int (*p)[3]=new int [3][3]
不规则的多维数组
int **array;
NULL升级
NULL: #define NULL (void *)0//0地址
C++中nullptr
char *ptr = nullptr;
函数的升级
C++对C的升级:函数的升级
引入inline关键字修饰函数:用(内存)空间换运行时间
引入默认参数:可以给形参设定默认参数 规则默认参数的右边参数必须全为默认参数
可以函数重载:可以使用相同的函数名 重载规则:形参的个数、类型或者顺序不同
注意事项:函数返回值不能作为重载条件,默认参数会影响重载规则
int add(int a,int b)
{
}
int add (int a,int b,int c)//个数不同
{
}
int add(char a, char b)
{
}
int add(int a,string b,int )//参数占位
{
}
add(6,5);
add(6,5);
add(6,5);
…
inline int add(int a, int b)//内联函数
{
return a+b;
}
嵌入式笔记24 命名空间 输入和输出 C++对C的升级相关推荐
- 《Python零基础快乐学习之旅》学习笔记4——基本输入与输出
第4章 基本输入与输出 4.1 Python的辅助说明help() help()函数可以列出某一个Python的指令或函数的使用说明. >>> help(print) Help on ...
- 神经网络与深度学习——TensorFlow2.0实战(笔记)(三)(python输入和输出)
从程序中学习知识点 1. #输出函数可以输出字符串常量 print("hello") #输出数学表达式 print(1+2) #输出变量 print(num) 2. #string ...
- csv java 科学计数法_Java入门笔记1/0(输入与输出)
0.输出: (0).System.out.println() 表示输出后换行 (1).System.out.print() 表示输出后不换行 1.格式化输出: (0).计算机有时输出的结果不一定被人很 ...
- labview学习笔记1-数字输入与输出
1.数字输入 labview与NI-max是不能相分离的,我们首先需要在NI-max中创建虚拟的数字板卡,具体操作下面说明. 首先我们需要安装NI-max,没有安装包的小伙伴可以在评论中自取,这里小编 ...
- linux路由相关函数,Linux 路由 学习笔记 之十一 输入、输出路由查找相关的接口函数...
对于路由功能模块的学习,也已经很长时间了.关于路由项的创建与查找.策略规则相关的创建与查找.路由缓存的创建与查找,都是分开来分析的,没有说明这些模块是如何配合使用的,以及模块之间的联系.本节就分析一下 ...
- python 输入输出转web_云计算开发学习笔记:Python3 输入和输出方式
Python两种输出值的方式: 表达式语句和 print() 函数.第三种方式是使用文件对象的 write() 方法,标准输出文件可以用 sys.stdout 引用. 如果你希望输出的形式更加多样,可 ...
- 【C++要笑着学】关键字 | 命名空间 | 输入和输出
- 1、存在如下数列1、1、2、4、7、13、24、44、81、149......现要求该数列第n项的值(n从O开始算)。 程序运行结果: 1/2 输入:4 输出:7 输入:9 输出:149
** 题目 ** /* 1.存在如下数列1.1.2.4.7.13.24.44.81.149-现要求该数列第n项的值(n从O开始算). 程序运行结果: 1/2 输入:4 输出:7 输入:9 输出:149 ...
- 二.编写第一个c#程序(注释,命名空间,类,Main方法,标识符,关键字,输入,输出语句,)...
复习编写一个控制台应用程序,目标是在控制台输出"Hello World" 1.第一步,打开Visual Studio 2012以上版本(我用的是VS 2015),打开完成后出现以下 ...
最新文章
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
- synchronize和lock的区别 synchionzie与volatile的区别
- 如何解析字符串类型的xml
- 矩阵分析与多元统计12 0-1矩阵 交换矩阵与Kronecker乘积
- JavaScript 数组你都掰扯不明白,还敢说精通 JavaScript ?| 赠书
- Python内置字符串函数的用法
- mysql官网社区免费版下载方法
- 学习Java可以干什么?
- 对于pdf转图片linux乱码的解决
- tx2 安装 Anaconda
- 以图搜图(基于 Milvus 和 VGG 实现以图搜图)
- 武林传奇之七剑下天山java游戏开发商_宝3武林传奇之七剑下天山的配方
- 超级跑车法拉利的历史
- Android UI最佳实践
- 【全网独家,收藏吧】10年全部《信息资源管理》真题整理,第2章 信息化规划与组织
- object mapping for [details] tried to parse field [details] as object, but found concrete value
- php三层架构 注册登陆,什么是三层架构
- 华为交换机 access,trunk,hybrid理解,需一点基础,应该是最完整的
- 概率论(离散型)极简入门
- 程序员这样使用电脑,想卡都超级难!