1.命名空间
①来源:名字冲突就是在同一个作用域中有两个或多个同名的实体,为了解决命名冲突C++中引入了命名空间
 ②定义:命名空间又称为名字空间,是程序员命名的内存区域,程序员根据需要指定一些有名字的空间域,把一些全局实体分别存放到各个命名空间中,从而与其他全局实体分隔开。通俗的说,每个名字空间都是一个名字空间域,存放在名字空间域中的全局实体只在本空间域内有效
 ③作用:程序员根据需要指定一些有名字的空间域,把一些全局实体分别存放到各个命名空间中,从而与其他全局实体分隔开防止冲突
 
 ④命名空间的使用方式:using编译指令、作用域限定符、using声明机制。
 using namespace std; -》》其中std代表的是标准命名空间
 下面是直接使用会可能造成错误的情况
 1)using编译指令
 
 2)作用域限定符:直接使用作用域限定符::,每次要使用某个名称空间中的实体时,都直接加上
 
 3)using声明机制
 using声明机制的作用域:从using语句开始,到using所在的作用域结束。(要注意,在同一作用域内用using声明的不同的命名空间的成员不能有同名的成员,否则会发生重定义)
 
 ⑤匿名命名空间:其实匿名命名空间和static是同样的道理,都是只在本文件内有效,无法被其它文件引用
 
 ⑥命名空间的嵌套及覆盖
 
 ⑦ 对命名空间的思考和总结
 1)提倡在已命名的名称空间中定义变量,而不是直接定义外部全局变量或者静态全局变量。
 2)如果开发了一个函数库或者类库,提倡将其放在一个名称空间中
 3)对于using 声明,首先将其作用域设置为局部而不是全局
 4)不要在头文件中使用using编译指令,这样,使得可用名称变得模糊,容易出现二义性,
 5)包含头文件的顺序可能会影响程序的行为,如果非要使用using编译指令,建议放在所有#include预编译指令后。
 6)包含头文件的顺序可能会影响程序的行为,如果非要使用using编译指令,建议放在所有#include
 预编译指令后。
2.const关键字的用法
- const关键字修饰变量

除了这种方式可以创建常量外,还可以使用宏定义的方式创建常量 
#define NUMBER 1024 
 
问题:
 常考题:const常量与宏定义的区别是什么?
 1)编译器处理方式不同。宏定义是在预处理阶段展开,做字符串的替换;而const常量是在编译时。
 2)类型和安全检查不同。宏定义没有类型,不做任何类型检查;const常量有具体的类型,在编译期会执行类型检查。在使用中,应尽量以const替换宏定义,可以减小犯错误的概率。
 2. const关键字修饰指针
 
- const关键字修饰成员函数
 - const关键字修饰对象
 
3.new/delete表达式
C中用来开辟和回收堆空间的方式是采用malloc/free库函数,在C++中提供了新的开辟和回收堆空间
 的方式,即采用new/delete表达式。
 1.开辟一个元素的空间
 
 2.开辟一个数组的空间
 
 常考题:new/delete表达式与malloc/free的区别是?
 1)malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符或表达式 ;
 2)new能够自动分配空间大小,malloc需要传入参数;//new自动
 3)new开辟空间的同时还对空间做了初始化的操作,而malloc不行;//new增加了对空间的初始化操作
 4)new/delete能对对象进行构造和析构函数的调用,进而对内存进行更加详细的工作,而malloc/free不能。//new还能进行更多功能的调用
 (既然new/delete的功能完全覆盖了malloc/free,为什么C++还保留malloc/free呢?因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。)
4.引用
1.什么是引用
 在理解引用概念前,先回顾一下变量名。变量名实质就是一段连续内存空间的别名。那一段连续的内存空间只能取一个别名吗? 显然不是,引用的概念油然而生。在C++中,引用是一个已定义变量的别名。
 其语法是:
 
 在使用引用的过程中,要注意以下几点:
- &在这里不再是取地址符号,而是引用符号,相当于&有了第二种用法
 - 引用的类型必须和其绑定的变量的类型相同
 - 声明引用的同时,必须对引用进行初始化,如上的int &ref2;否则编译时报错
 - 一旦绑定到某个变量之后,就不会再改变其指向
 
2.引用的本质
 ①C++中的引用本质上是一种被限制的指针。
 ②由于引用是被限制的指针,所以引用是占据内存的,占据的大小就是一个指针的大小。有很多的说法,都说引用不会占据存储空间,其只是一个变量的别名,但这种说法并不准确。引用变量会占据存储空间,存放的是一个地址,但是编译器阻止对它本身的任何访问,从一而终总是指向初始的目标单元。在汇编里, 引用的本质就是“间接寻址”。在后面学习了类之后,我们也能看到相关的用法。
 3.引用作为函数参数
 ①引用的作用:在很多场合下就可以用引用代替指针,因而也具有更好的可读性和实用性。这就是引用存在的意义
 
 ②参数传递的方式除了上面的指针传递和引用传递两种外,还有值传递。采用值传递时,系统会在内存中
 开辟空间用来存储形参变量,并将实参变量的值拷贝给形参变量,即形参变量只是实参变量的副本而已;注意如果函数传递的是类对象,系统还会调用类中的拷贝构造函数来构造形参对象,假如对象占据的存储空间比较大,那就很不划算了。这种情况下,强烈建议使用引用作为函数的形参,这样会大大提高函
 数的时空效率。
 4.引用作为函数的返回值
 
当引用作为函数的返回值时,必须遵守以下规则:
 5. 不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
 6. 不能在函数内部返回new分配的堆空间变量的引用。如果返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么该引用所在的空间就无法释放,会造成内存泄漏。
 
 引用总结:
 7. 在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递
 中,解决大块数据或对象的传递效率和空间不如意的问题。
 8. 用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,
 保证了引用传递的安全性。
 9. 引用与指针的区别是,指针通过某个指针变量指向一个变量后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
5.C++强制转换
1)c++为了克服这些缺点:①c风格的转换不容易查找,它由一个括号加上一个标识符组成,而这样的东西在c++程序里一大堆;②把一个指向const对象的指针转换成指向非const对象的指针,把一个指向基类对象的指针转换成指向一个派生类对象的指针,这两种转换之间的差别是巨大的,但是传统的c语言风格的类型转换没有区分这些
 2)
 ①static_cast
 最常用的类型转换符,在正常状况下的类型转换, 用于将一种数据类型转换成另一种数据类型,如把int转换为float
 
 也可以完成指针之间的转换,例如可以将void*指针转换成其他类型的指针
 
 但不能完成任意两个指针类型间的转换
 
 总结,static_cast的用法主要有以下几种:
 1)用于基本数据类型之间的转换,如把int转成char,把int转成enum。这种转换的安全性也要开发人
 员来保证。
 2)把void指针转换成目标类型的指针,但不安全。
 3)把任何类型的表达式转换成void类型。
 4)用于类层次结构中基类和派生类之间指针或引用的转换。进行上行转换(把派生类的指针或引用转换
 成基类指针或引用)是安全的;进行下行转换(把基类指针或引用转换成派生类指针或引用)时,由于没有动态类型检查,所以是不安全的。
 2.const_cast
 该运算符用来修改类型的const属性。常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。
 
3. dynamic_cast
 该运算符主要用于基类和派生类间的转换,尤其是向下转型的用法中。
 4. reinterpret_cast
 该运算符可以用来处理无关类型之间的转换,即用在任意指针(或引用)类型之间的转换,以及指针与足够大的整数类型之间的转换。由此可以看出,reinterpret_cast的效果很强大,但错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确
 使用reinterpret_cast方式。
6、函数重载
在实际开发中,有时候需要实现几个功能类似的函数,只是细节有所不同。如交换两个变量的值,但这两种变量可以有多种类型,short, int, float等。在C语言中,必须要设计出不同名的函数,其原型类似于:
 
7、默认参数
C++可以给函数定义默认参数值。通常,调用函数时,要为函数的每个参数给定对应的实参,
 
如果一个函数中有多个默认参数,则形参分布中,默认参数应从右至左逐渐定义。当调用函数时,只能向左匹配参数。如
 
 默认参数与函数重载,默认参数可将一系列简单的重载函数合成为一个。例如:
 
 如果一组重载函数(可能带有默认参数)都允许相同实参个数的调用,将会引起调用的二义性。
8.bool类型
在C++中,还添加了一种基本类型,就是bool类型,用来表示true和false。true和false是字面值,可以通过转换变为int类型,true为1,false为0.
 
 任何数字或指针值都可以隐式转换为bool值。
 任何非零值都将转换为true,而零值转换为false.
 
 9.inline函数
 内联函数作为编译器优化手段的一种技术,在降低运行时间上非常有用
 1.什么是内联函数?
 用来降低程序的运行时间。当内联函数收到编译器的指示时,即可发生内联:编译器将使用函数的定义体来替代函数调用语句,这种替代行为发生在编译阶段而非程序运行阶段。
 (定义函数时,在函数的最前面以关键字“inline”声明函数,即可使函数称为内联声明函数。)
 
 2. 内联函数和带参数的宏定义
 1.使用宏代码的缺点:
 ①容易出错,预处理器在拷贝代码时经常产生想不到的边际效应
 ②不可调试,但是内联函数可以调试
 ③无法操作类的私有数据成员
 ④优点:可以通过上下文相关的优化技术对结果代码进行更深入的优化
 3.谨慎使用内联函数
 
 10.异常安全
 异常是程序在执行期间产生的问题。C++ 异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作。异常提供了一种转移程序控制权的方式。C++ 异常处理涉及到三个关键字:try、catch、throw。
①throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
 
②try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。
 理论:
 
 举例:
 
③catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常。
额外补充:
 cin相当于scanf输入数据
 endl表示加个回车
 cout,标准输出,相当于printf
 这个>>输入流运算符
 而<<,输出流运算符
#include <stdio.h>
#include <iostream>//C++头文件没有加.h,因为C++头文件都是用模板写的,
                   //而模板有个特点:必须要知道所有实现之后才能正常编译
using namespace std;//命名空间
//函数的声明
//函数声明可以有多次,函数定义只能有一次
void test();
void test();
void test();
void test();
void test();
void test()
{
   
}
int main(int argc, char **argv)
{
   
    /* &10;//error,字面值常量,不能取地址 */
    /* &"Hello, world";//ok */
    //cout,标准输出
    //<<,输出流运算符
    //"Hello world",字符串常量
    //endl end of line
    cout << "Hello world" << endl;
    operator<<(cout, "Hello world").operator<<(endl);//运算符重载
    int number = 0;
    //cin,标准输入
    //>>,输入流运算符
    cin >> number;
    cout << "number = " << number << endl;
    return 0;
}
转载:https://blog.csdn.net/weixin_43679037/article/details/116407131