1. nullptr
nullptr是C++11的新关键字,用于取代NULL。
#include <iostream>
using namespace std;
void func(int)
{
cout << "A" << endl;
}
void func(char*)
{
cout << "B" << endl;
}
int main()
{
func(NULL); // A
}
上面的代码中调用第二个函数比较合理,但是实际运行调用的是第一个函数,因为NULL就是0。
#include <iostream>
using namespace std;
void func(int)
{
cout << "A" << endl;
}
void func(char*)
{
cout << "B" << endl;
}
int main()
{
func(NULL); // A
func(nullptr); // B
}
使用nullptr可以区分0和空。
2. 类型推导
在C++11中,可以使用auto和decltype关键字进行类型推导。
#include <iostream>
using namespace std;
int main()
{
auto a = 1; // auto被自动推导为int
auto b = new auto(2); // auto被自动推导为int*
cout << a << endl; // 1
cout << *b << endl; // 2
delete b;
}
使用decltype推导表达式类型时,编译器只会计算类型而不计算数值。
#include <iostream>
using namespace std;
int main()
{
// decltype可以对表达式进行类型推导
auto x = 1;
auto y = 2;
decltype(x+y) z = 123;
cout << z << endl;
}
3. 初始化列表
C++11中引入了初始化列表语法(列表初始化、通用统一初始化、一致性初始化),使用{}进行初始化。
#include <iostream>
using namespace std;
class Student
{
private:
int id;
string name;
public:
Student(int id,string name):id{id},name{name}{}
void print()
{
cout << id << " " << name << endl;
}
};
int main()
{
int a{1};
cout << a << endl;
int b{};
cout << b << endl; // 0
int arr[] = {1,2,4}; // 推导数组长度为3
for(int i=0;i<3;i++)
cout << arr[i] << " ";
cout << endl;
Student s = {1,"张三"};
s.print();
}
【思考】一共学习了哪些C++11新特性?
- for-each
- array
- nullptr
- 类型推导
- 初始化列表、窄化
- 智能指针
- 继承构造
- override关键字
- 类型转换
- constexpr
4. 格式化输出
4.1 进制
使用cout输出时,可以切换进制:
#include <iostream>
using namespace std;
int main()
{
cout << dec; // 切换到十进制输出(默认)
cout << 1234 << endl;
cout << oct; // 切换到八进制
cout << 8 << endl; // 10
cout << hex; //切换到十六进制
cout << 255 << endl; // ff
}
为了区分不同的进制显示,可以增加显示进制的功能:
#include <iostream>
using namespace std;
int main()
{
cout << showbase; // 进制显示
cout << dec << 1234 << endl; // 十进制就是正常显示
cout << oct << 3434 << endl; // 八进制前面补0
cout << hex << 2344 << endl; // 十六进制前面补0x
cout << noshowbase; // 关闭进制显示
cout << dec << 1234 << endl;
cout << oct << 3434 << endl;
cout << hex << 2344 << endl;
}
4.2 域
可以使用setw函数指定输出内容占用的宽度:
- 如果设定域的宽度大于数据本身的宽度,显示为设定域的宽度;
- 如果设定域的宽度小于数据本身的宽度,显示为数据本身的宽度。
每次都需要在输出前使用setw函数,使用前需要引入头文件 #include <iomanip>
#include <iostream>
#include <iomanip> // 头文件
using namespace std;
int main()
{
cout << setw(10) << "12c";
cout << setw(6) << "12c8787878";
cout << setw(6) << "12c";
}
5. 文件流
使用C++实现一个文件拷贝的程序:
#include <iostream>
#include <fstream> // 头文件
using namespace std;
int main()
{
ifstream ifs("E:\\bbq.mp4",ios_base::binary); // 文件输入流对象
if(!ifs)
{
cout << "读取失败!" << endl;
return 0;
}
ofstream ofs("C:\\Users\\jngwu\\Desktop\\bbq(2).mp4",
ios_base::binary); // 文件输出流对象
if(!ofs)
{
cout << "无法保存!" << endl;
return 0;
}
// 使用数组作为缓存
char buffer[1024];
long long size = 0; // 文件大小
long long has_copied = 0; // 已经读写的大小
// 文件指针从头部移动到尾部
ifs.seekg(0,ios::end);
streampos ps = ifs.tellg(); // 获取文件的移动量
cout << "移动量:" << ps << endl;
size = ps;
// 文件指针移动回头部
ifs.seekg(0,ios::beg);
// 循环读写
while(ifs)
{
// 读取数据
ifs.read(buffer,1024);
//gcount返回39行读取的数据量
int copy_size = ifs.gcount();
has_copied += copy_size; // 累积读写的数据量
// 输出数据
ofs.write(buffer,copy_size);
// 百分比显示
cout << 100*has_copied/size << endl;
}
// 收尾
ifs.close();
ofs.flush();
ifs.close();
}