目标
- c++关键字
- 命名空间
- c++输入和输出
- 缺省参数
- 函数重载
- 引用
- 内联
- auto关键字
- 基于范围的for循环
- 指针空值
c++关键字

命名空间
c/c++中 ,变量、函数等都在全局中,容易造成冲突,使用命名空间对标识符的名称进行本地化 ,避免冲突(java是报名来分离)
- 命名空间的定义
需要使用到namespace关键字,后面加上的就是命名空间的名字。然后接一对{},在花括号里面的就是命名空间的成员。
namespace t1{
int mm ;
int max(int m1,int m2){
return m1>m2?m1:m2;
}
}
并且一个类中可以存在多个命名空间,命名空间中的内容仅限于该命名空间中。
- 命名空间的使用
命名空间的使用有三中方式
方式一:命名空间::变量
std::string
方式二:使用using namespace导入
使用using name std
方式三:使用using
using t1::mm
输入输出
c++版本的hello world,顺便看一下命名空间
- 使用std::xxx的方式
#include <iostream>
int main()
{
std::cout << "Hello World!\n";
}
- 使用using的方式
using std::cout;
int main() {
cout << "HELLO";
return 0;
}
- 使用namespace
using namespace std;
int main() {
cout << "HELLO";
return 0;
}
标准的输出
- 加入头文件
- 使用命名空间
输入
输入只需要直接使用cin即可。
using namespace std;
int main() {
int a = 10;
cout << a;
cin >> a;
cout << a;
return 0;
}
缺省参数
java中是没有这个备胎的。
缺省参数就是没有指定的时候,使用默认值。
来个例子
int method(int a = 10){
cout<<a;
}
默认使用的是10
method();
使用的是我传入的
mehtod(22);
- 全缺省和半缺省
全省
int xx(int a = 1;int b = 2;int m= 3){
}
半省
int xx(int a;int b = 2;int m= 3){
}
从右向左给出 ,不可以间隔;不可以在定义和实现的地方同时出现
重载
重载是函数的一种特殊情况,c++允许在同一个作用域中声明几个功能类似的同名函数 ,同名函数的列表的个数或类型或顺序不同,,常用来实现不同的功能。
int add(int left ,int right){
retuen left+right;
}
//类型不同
double add(double left,double right){
return left + right;
}
返回值不同不能认为是重载
int add(int a,int b){}
void add(int a,int b){}
名字修饰
一个程序运行需要预处理、编译、汇编、链接
预处理之后会生成xx.i文件,然后编译生成.s文件。汇编形成,.o文件,最后通过链接 ,将其他的库和目标文件达成目标文件。
名字修饰符就是在执行的
对于函数的重载,可以查看报错类型
extern "c"
有时候c++需要是c的某种风格进行编译,函数前加extern "C"
extern "C" int method(int a,int b);
int main(){
method(1,2);
return 0;
}
问:为什么c不可以使用重载?
因为名字修饰的原因,它的编译器的底层实现是不同的。
引用
概念:不是一个新定义的一个变量,而是取一个别名,不会为它开辟空间,它们使用同一块内存。
using namespace std;
int main() {
int i = 10;
int& a = i;
printf("%d",a); //输出值
printf("%d",&a);//输出地址
printf("%d", &i);//输出地址
return 0;
}
它们的地址是一样的
引用类型的特性
- 引用在定义的时候必须初始化
int i = 0;
int &a = i;
int &b; //错误 需要初始化
- 一个变量可以有多个引用
int i = 0;
int &a = i;
int &b = i;
int &c = i; //可以有多个引用
- 引用一旦引用一个实体,在也引用不了其他实体了。
int i = 1;
int j = 2;
int &a = i;
&a = j;//错误
这个我认为在初始化之后就不能在进行重新赋值(描述可能不是很准确)
常引用
- 常量不可以引用
const int a = 10;
int &aa = a;//a为常量
int &bb = 10;//a为常量
- 类型于要求
double d = 12.33;
int &re = d;类型不同
引用类型的使用场景
- 做参数
void swap(int &i,int &j){
int a = i;
i = j;
j = a;
}
- 做返回值(java一般是返回值,c++一般是把地址给出去)
int& add() {
//return 1;//不对是因为常量不能做引用类型
int a = 1;
return a;
}
int a = add();
cout << a; //打印是值
int &b = add();
cout<<b;//打印的也是值
这个存在拥有一个问题 ,新的方法在栈上开辟空间 ,方法执行完了,这个空间就没有了,我们以这种方式得到值,可能在使用的时候地址已经回收,可能就会出错。
为什么需要引用传递
引用传递的是什么东西,一个地址,无论是什么类型,都值传递一个地址。值传递传的是一个数据的拷贝。
指针和引用的区别是什么?
- 之前说过的,引用必须创建的时候初始化
- 引用只能引用一个
- 引用的大小为类型的大小,指针是一个固定大小
- NULL指针 (有) NULL引用(没有)
- 偏移不同,指针偏移一个类型(数组),引用不是
- 引用相对安全
- 指针自己写,引用编译器处理
内联函数
inline修饰的函数叫内联函数,内联函数会在调用的时候展开,不会有栈的开销(调用方法会存在入出栈操作)。
- 属于使用空间换取时间,
auto关键字
auto修饰变量,是具有自动存储器的局部变量。auto在11作为一个新的类型指示编译器。
- 定义的时候必须进行初始化(编译器会自己推到类型),编译的时候会变为实际类型。
- auto使用规则
auto与指针和引用结合起来使用,auto声明类型的时候,使用auto和auto*没区别,但是声明引用类型需要加上&
int main(){
int x =10;
auto a = &x;
auto *b = &x; 上面两个没区别
auto &c = x;引用类型需要加&
}
一行可以定义多个 变量
auto a = 1 ,b = 2;
不可以推导的场景
首先不可以作为参数
void xx (auto a){
}
不可以声明数组
不可以定义非静态成员变量
实现模板是不能使用auto作为模板参数
c++11的for
想一下for循环
int a[]={1,3,4,5,6,7};
for(int i=0;i<sizeof(arr)/sizeof(array[0]);i++){
}
改版后的
int aa [] = {1,3,4,5,6};
for(auto &e : aa){
}
- for的使用条件
for的范围必须是确定的,比如 通过一个函数传递过来的,我们谁也不知道这个数组的大小。所以使用上面的方法就不合适了。
迭代对象需要实现++ ==操作(这句话 不理解)
nullptr
声明一个变量最好给一个合适的初始值,不然不知道这个会指向哪里。
int *p = NULL;
int *p = 0 ;
NULL是一个宏
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
- nullptr和nullptr_t
c98 NULL
c++11给出了一个nullptr
建议使用nullptr 它不需要引入头文件,因为作为关键字引入的。
网友评论