第一章 C++ 基础
前言
C++ 是 C语言 的超集,是一门在 C语言 基础上发展起来的语言。所以C语言的语法在C++都通用,所以这里就不会介绍C语言与C++相同的语法了。
写博客是为了记录下学习C++的而做的笔记。防止自己遗忘。如果你正在学习C++,而刚好又是很无聊(上课、一个人走在路上)的时候,你可以试着看一看。
正文内容
关键字
看过就行了,后面会了解的。
第一个程序
#include<iostream> //头文件
using namespace std; //全局展开std命名空间
int main()
{
// cout 是输出函数
// << 流插入运算符,配合 cout 使用
// endl 换行符,相当于 \n
cout << "Hello World!" << endl;
return 0;
}
命名空间
通过不同命名空间将 变量/函数 限定使用,避免两个相同变量起冲突
#include <iostream>
namespace first{
int x = 1;
}
namespace second{
int x = 2;
}
int main() {
using namespace second;
int x = 3;
// 这里没有展开 std 命名空间 需要使用 std::
std::cout << x << std::endl; // 3
std::cout << first::x << std::endl; // 1
std::cout << second::x << std::endl; // 2
return 0;
}
展开方式
全局展开
using namespace 命名空间; //全局展开覆盖范围为整个程序
//比如上面代码中
using namespace first; //全局展开first这个命名空间,可以在任意位置使用first中的变量/函数
部分展开
using 命名空间::待使用变量/函数;
//比如
using second::x; //只展开second中的变量x,此时可在任意位置使用second中的变量x
注意:
域作用限定符
//需要使用时
cout << 命名空间::待使用变量/函数 << endl; //需要使用时展开
//比如
std::cout << second::x << std::endl; //这个就是使用时展开
//注意:假设 :: 左边为空,如 ::x这种情况,会去全局范围内查找变量x,如果没有找到,就会报错
tips:: 命名空间支持嵌套使用
缺省参数
在函数声明时,为形参设定初始值。当有实参传入,就使用实参;没有就使用初始值。
#include <iostream>
void print_love(char name = 'H' )
{
std::cout << "I LOVE " << name << std::endl;
}
int main() {
print_love(); // I LOVE H
print_love('h'); //I LOVE h
return 0;
}
补充:图中这样也可以(适用自定义类型),会输出 I LOVE
( char() -> '' ),( int() -> 0 )
注意事项:
1、只允许从右到左依次连续缺省,不得出现跳跃缺省
2、调用时,实参依次从左往右传递
3、声明和定义中不能同时出现缺省参数,只能在声明中出现
4、C语言不支持缺省参数
函数重载
C语言是不允许两个函数名字相同的,比如函数 Add 只能适用于一种数据类型,在 C++ 中支持函数重载,即在参数个数不同(包括类型不同或顺序不同)的前提下,允许同时存在多个同名函数
注意: 返回值不纳入函数名修饰中
引用
int a = 10;
int* pa = &a; //指针
int& ra = a; //引用
引用相当于给变量取别名(智能版指针会自动解引用)。
可用于做函数参数(效率高),做返回值。
使用规则:
1.引用必须初始化,当一个引用变量被创建时,必须存在其所代表的变量
2.一个变量可以存在多个引用
3.当引用初始化后,无法再代表其他变量
4.不存在多级引用,当 引用b 代表 引用a 时,实际上就是在代表 引用a 所代表的变量 a
常引用
指针和引用具有直接修改原数据的能力,加上 关键字 const 变成 只读不可写,权限不可放大(只能平移或缩小)
小结
引用在概念上是给变量取别名,而指针是新开一块空间指向变量
引用必须初始化,指针可以不初始化
引用无法改变指向,指针可以
不存在空引用,但存在空指针
引用大小为所代表变量的大小,而指针大小为 4/8 字节
引用+1等价于变量+1,指针+1则表示指向位置向后偏移一个单位
引用不需要解引用,指针使用前需要解引用
引用使用起来更安全、更方便
以后涉及需要改变原变量值时,优先考虑使用引用,特殊场景下,仍然需要使用指针
引用与指针互不冲突,两者都有自己适用的领域,比如在实现链表时,必须使用指针,因为引用无法改变指向,而链表需要频繁的进行改链操作
内联函数
内联函数主要是为了替代宏函数
内联函数就是在函数实现前加上 inline 修饰,此时函数会被编译器标记为内联函数
内联函数特点:
在 Debug 模式下,函数不会进行替换,可以进行调试
在 Realse 模式下,函数会像宏函数一样展开,提高程序运行速度
内联函数弥补了宏函数的不足,同时吸收了宏函数速度快的优点
内联函数可以全面替代宏,当然使用时也需要注意
频繁使用内联函数,编译出来的可执行程序会更大,因为代码会变多,但运行速度更快
调用内联函数时,是否展开取决于编译器,如果内联函数展开后会影响性能,那么编译器有权不展开内联函数
内联函数适用于代码行数较少,且被频繁调用的小函数
内联函数不建议声明和定义分开,因为内联函数不进入符号表,因此可能产生链接错误,推荐在声明时就顺便将函数定义,头文件展开时,将内联函数一起包含
C++11 中的新特性
auto
auto 关键字能直接识别目标变量类型,然后自动转换为相应类型。
int a = 10;
auto& b = a; // auto 可以指定类型转换
b = 20;
auto c = a; // auto 自动适应类型
c = 30;
std::cout << a << std::endl; // 20
std::cout << c << std::endl; // 30
auto 支持一行声明多个变量,当然类型得统一
注意: auto 不能用于数组,auto 也不能当作参数类型
范围for
int a[] = { 1,2,3,4,5,6 };
for (auto& num : a) { // 范围for
num *= 2;
std::cout << num << ' ';
}
nullptr
nullptr 是作为关键字加入的,不需要头文件
nullptr 和 void* 的大小一致
int* p2 = nullptr; // 空指针建议这样
为什么?那就在看一个例子:
#include<iostream>
using namespace std;
void func(int)
{
cout << "参数为整型 0" << endl;
}
void func(void*)
{
cout << "参数为指针 void*" << endl;
}
int main()
{
func(0); // 参数为整型 0
func(NULL); // 参数为整型 0
func(nullptr); // 参数为指针 void*
return 0;
}
总结
在学C++的路上难免会遗忘一些知识,所以我写下博客记上笔记,只为减缓遗忘。