0%

C++11/14 特性介绍(一)

本系列整理转载实验楼的 C++11/14 教程,对 C++11/14 中出现的部分重要特性进行介绍。

前言

C++1x (指 C++11/14, 甚至 C++17) 为传统 C++ 注入的大量特性使得整个 C++ 变得更加像一门现代化的语言。C++1x 不仅仅增强了 C++ 语言自身的可用性,auto 关键字语义的修改使得我们更加有信心来操控极度复杂的模板类型。同时还对语言运行期进行了大量的强化,Lambda 表达式的出现让 C++ 具有了『匿名函数』的『闭包』特性,而这一特性几乎在现代的编程语言(诸如 Python/Swift/… )中已经司空见惯,右值引用的出现解决了 C++ 长期以来被人诟病的临时对象效率问题等等。

C++1x 为自身的标准库增加了非常多的工具和方法,诸如在语言层面上提供了 std::thread 支持了并发编程,在不同平台上不再依赖于系统底层的 API,实现了语言层面的跨平台支持;std::regex提供了完整的正则表达式支持等等。

C++98 已经被实践证明了是一种非常成功的『范型』,而 C++1x 的出现,则进一步推动这种范型,让 C++ 成为系统程序设计和库开发更好的语言。

编译 C++1x 代码至少需要开启 -std=c++11 选项来支持 C++11 相关特性,在介绍 C++14 特性时的相关代码需要开启 -std=c++14 的编译选项,例如:

1
2
g++ main.cpp -std=c++11
g++ main.cpp -std=c++14

本文先介绍被弃用的特性和与C的兼容性的一些参考

被弃用的特性

主要是从C++11开始,被弃用的特性。

被弃用不等于不能使用,出于兼容性,有些特性暂时甚至会永久保留

  • 如果一个类有析构函数,为其生成拷贝构造函数和拷贝赋值运算符的特性被弃用了。

  • 不再允许字符串字面值常量赋值给一个 char 。如果需要用字符串字面值常量赋值和初始化一个 char ,应该使用 const char * 或者 auto。

1
2
3
4
char *str = "hello world!"; // 将出现弃用警告

auto str = "hello world!"; // 正确
const char *str = "hello world!"; // 正确
  • C++98 异常说明、 unexcepted_handler、set_unexpected() 等相关特性被弃用,应该使用 noexcept。

  • auto_ptr被弃用,对应使用unique_ptr。

  • register关键字被弃用。

  • bool类型的++操作被弃用。

  • C风格的强制转换被弃用,改用static_cast、reinterpret_cast、const_cast 来进行类型转换。

与 C 的兼容性

出于一些不可抗力、历史原因,我们不得不在 C++ 中使用一些 C 语言代码(甚至古老的 C 语言代码),例如 Linux 系统调用。在编写 C++ 时,也应该尽可能的避免使用诸如 void 之类的程序风格。而在不得不使用 C 时,应该注意使用 extern “C” 这种特性,*将 C 语言的代码与 C++代码进行分离编译,再统一链接这种做法,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// foo.h
#ifdef __cplusplus
extern "C" {
#endif

int add(int x, int y);

#ifdef __cplusplus
}
#endif

// foo.c
int add(int x, int y) {
return x+y;
}

// main.cpp
#include "foo.h"
int main() {
add(1, 2);
return 0;
}
  1. 首先使用gcc来编译C语言的代码:

gcc -c -o foo.o foo.c

注意-c参数

  1. 然后使用 g++ 将 C++代码和 .o 文件链接起来(或者都编译为 .o 再统一链接):

g++ main.cpp foo.o -o main

结语

本文先对本系列进行一个开始,后续特性将在系列中逐一介绍。

实验楼原文连接