本文包含的知识点:命名空间及其使用,c++的输入输出,缺省参数,函数重载,引用,const引用,inline内联函数
一、命名空间
为了解决在大型项目中变量,函数和类的命名冲突,c++中引入了命名空间,他可以保证开发者在自己需要调用的地方调用自己需要的变量,函数和类。
使用方式
namespace fish
{
int rand = 10;
int ADD(int a,int b)
{
return a+b;
}
struct node
{
struct node* next;
int val;
};
}
用这样,就可以实现定义一个空间,这样可以保证不会出现冲突问题,如要访问,则要
cout<<fish::rand<<endl;
命名空间 + :: + 命名,通过::即可访问命名空间。
同样的,命名空间可以进行嵌套,比如
namespace fish
{
int rand = 10;
int ADD(int a,int b)
{
return a+b;
}
struct node
{
struct node* next;
int val;
};
namespace bigfish
{
int rand = 1;
}
}
对于嵌套,我们的访问方式同上
cout<<fish::bigfish::rand<<endl;
这便是实现了初步的使用
在实际使用中,我们对于一些经常使用的空间,可以直接使用using展开,例如
namespace fish
{
int rand = 10;
int ADD(int a, int b)
{
return a + b;
}
}
int main()
{
using namespace std;
using namespace fish;
int a = 1, b = 2;
cout << ADD(a, b) << endl;
return 0;
}
在展开之后,就无需使用::来进行访问,相当于在原位置把这些代码给复制过来,上诉代码中的std命名空间,是c++中的标准库,包含了c标准中定义的全部类,函数,对象和模板。
二、c++的输入输出
需要包含的头文件 <iostream> 他是标准的输入输出库。
std::cin 用于面向窄字符的标准输入。
std::cout 它主要⾯向窄字符的标准输出流。
std::endl 一个函数,在输入输出的过程中,插入一个换行字符并且刷新缓冲区。
对于c++中的输入输出,他不需要手动指定格式,十分方便。
三、缺省参数
定义:在定义或者声明函数中为函数的参数指定的一个缺省值,在调用该函数时,如果没有指定的参数,则调用该缺省值。
其中有全缺省和半缺省两种,前者就是全部给缺省值,后者以部分形式给缺省值,其中规必须从右往左连续缺省,不能跳跃。同样的,调用的过程中,也必须从左往右以此给实参,不能跳跃。
声明和定义分离的时候,不能同时给缺省值。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
int add(int a = 1, int b = 2)
{
return a + b;
}
int main()
{
int a = 3, b = 4;
cout <<"全缺省" << add() << endl; // 全缺省
cout << "半缺省" << add(b) << endl; // 半缺省
cout << "无缺省" << add(a, b) << endl; // 无缺省
//不能这样 cout << "无缺省" << add(, b) << endl; //
return 0;
}
四、函数重载
c++中允许函数命名相同,但在使用中通过不同的参数实现不同类型的函数调用。
类型不同:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
void swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
void swap(char& x, char& y)
{
char temp = x;
x = y;
y = temp;
}
int main()
{
int a = 1, b = 2;
char c = 'A', d = 'B';
cout << "交换前: a = " << a << ", b = " << b << endl;
swap(a, b);
cout << "交换后: a = " << a << ", b = " << b << endl;
cout << "交换前: c = " << c << ", d = " << d << endl;
swap(c, d);
cout << "交换后: c = " << c << ", d = " << d << endl;
return 0;
}
个数不同:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
int add(int x, int y)
{
return x + y;
}
int add(int x, int y, int z)
{
return x + y + z;
}
int main()
{
int a = 1, b = 2, c = 3;
cout << add(a, b) << endl;
cout << add(a, b, c) << endl;
return 0;
}
还有不同类型参数顺序不同,这里就不过多赘述。
注意:返回值不同不能作为重载条件
// void fun()
//{}
//
//int fun()
//{
//
//return 0;
//}
此时编译器会报错,因为不能区分你要调用具体哪个。
五、引用
引入
关于引用的定义,他就相当于给已有的变量取了一个别名,他和被引用的对象使用的同一块内存。
使用方法 : 类型& 别名 = 引用对象;
不要和取地址(&)搞混了,虽然他俩就是一个符号。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
int main()
{
int a = 0;
int& b = a;
int& c = a;
int& d = b;
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
cout << &d << endl;
return 0;
}
运行结果
可以发现内存地址完全一样。
相关的特质
1、一个变量可以有多个引用。
2、引用使用中必须初始化,和指针不同。
3、引用一旦确定,就不能引用其他变量。
对于第三点,我们可以用一段代码来说明:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
int main()
{
int a = 0;
int& b = a;
int c = 1;
cout <<"a的地址:" << &a << endl;
cout << "b的地址:" << &b << endl;
cout << "c的地址:" << &c << endl;
cout << "进行操作前a的值:" << a << endl;
b = c;
cout << "进行操作后a的值:" << a << endl;
cout << "进行操作后的a的地址:" << &a << endl;
cout << "进行操作后的b的地址:" << &b << endl;
return 0;
}
以下是运行结果:
所以,这种操作实际是一种赋值。
我们可以发现,引用在很多场景中,可以替代指针,他会更高效,比如数据结构中的链式传输,就可以避免使用二级指针。例如:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
typedef struct Node
{
int data;
struct Node* next;
};
void push(Node*& head, int new_data)
{
Node* new_node = new Node;
new_node->data = new_data;
new_node->next = head;
head = new_node;
}
int main()
{
Node* head = (Node*)malloc(sizeof(Node));
head->data = 1;
head->next = NULL;
push(head, 2);
return 0;
}
我们可以发现,通过使用引用,可以极大的简化在数据结构中对指针的应用。
引用和指针相辅相成。
const引用
可以引用const对象,但是必须用同样的const引用,也可以引用普通对象,使用const引用。
核心——权限不能放大,只能缩小
注意,在c++中,表达式的值是存在一个临时对象中的,而类型转换也属于,而临时对象在这里是会具有一个常性,所以像下面:
int a = 1;
double b = 2.3;
//int& c = b; int& c = a * 3;
//会报错,因为在转换和计算中是常性,所以要用const修饰
const int& c = b; //像这样(const int& c = a * 3)
总结
指针和引用是相辅相成,在不同的地方有不同的作用,二者无法五项替代。
·引用是取别名,指针是开辟新空间存储地址。
·指针不用初始化,引用必须。
·引用不能改变引用的对象,但指针可以随时修改指代的对象。
六、inlie 内联函数
内联函数指用inline修饰的函数,他可以在调用的时候展开函数,可以提高效率。
inline int Add(int x, int y)
{
int re = x + y;
re += 1;
re += 1;
re += 1;
return re;
}
int main()
{
int ret = Add(1, 2);
cout << Add(1, 2) * 5 << endl;
return 0;
}
七、补充 关于nullptr
对于NULL,我们经常使用,比如在创建指针变量时,暂时给予NULL以防野指针,其本质是一种宏定义。
在c语言中
#define NULL (void*)0
这里是把0强转为指针的形式了,但是在c++中
#define NULL 0
在这种情况下就会出现问题。
void fun(int x)
{
cout << "fun(int x)" << endl;
}
void fun(int* x)
{
cout << "fun(int* x)" << endl;
}
所以我们引入了nullptr,来避免冲突。
void fun(int x)
{
cout << "fun(int x)" << endl;
}
void fun(int* x)
{
cout << "fun(int* x)" << endl;
}
fun(nullptr);