2.C++14,C++17特性-灵析社区

菜鸟码转

函数返回值类型推导:

函数返回类性也可以用 auto 类型,编译时会有编译器进行类型推导。

auto func(int i) {
    return i;
}

需要注意:

  • 函数内如果有多个 return 语句,它们必须返回相同的类型,否则编译失败。
  • 如果 return 语句返回初始化列表,返回值类型推导也会失败。
  • 如果函数是虚函数,不能使用返回值类型推导。
  • 返回类型推导可以用在递归函数中,但是递归调用必须以至少一个返回语句作为先导,以便编译器推导出返回类型。
  • 在 C++ 14 中,lambda 函数的形式参数允许泛型。

C++

auto lambda = [](auto x, auto y) {return x + y;}
lambda(1, 2);
lambda(1.0, 2.0);
Lambda 初始化捕获:
  • 允许在 lambda 捕获列表中对变量进行表达式赋值,并且支持定义新的变量并进行初始化。

C++

auto lambda = [value = 1] {return value;}
  • constexpr 函数限制变动:

C++ 11 中 constexpr 函数只含有一个将被返回的表达式,C++ 14 放松了这些限制:

除了 static 或 thread_local 变量 以外,可以声明新的变量,且声明的变量必须初始化。

可以包含条件分支语句 if 和 switch。

可以包含所有的循环语句,包括基于范围的for循环。

表达式可以改变一个对象的值,只需该对象的生命期在声明为 constexpr 的函数内部开始。

  • 变量模板:

C++

template<class T>
constexpr T pi = T(3.1415926535897932385L);

int main() {
    cout << pi<int> << endl; // 3
    cout << pi<double> << endl; // 3.14159
    return 0;
}
  • deprecated 属性

deprecated 属性允许标记不推荐使用的实体,该实体仍然能合法使用,但会让用户注意到使用它是不受欢迎的,并且可能会导致在编译期间输出警告消息。deprecated 可以使用字符串文字作为参数,以解释弃用的原因和/或建议替代者。

C++

[[deprecated]] int f();

[[deprecated("g() is thread-unsafe. Use h() instead")]]
void g( int& x );

void h( int& x );

void test() {
  int a = f(); // 警告:'f'已弃用
  g(a); // 警告:'g'已弃用:g() is thread-unsafe. Use h() instead
}
  • std::make_unique:

C++ 11 中有 std::make_shared,却没有std::make_unique,在 C++ 14 增加 std::make_unique。

C++

struct A {};
std::unique_ptr<A> ptr = std::make_unique<A>();
  • 共享的互斥体和锁

C++ 14 增加了一类共享的互斥体和相应的共享锁,通过使用 std::shared_timed_mutex 和 std::shared_lock 来进行线程同步。

C++ 17 新特性

  • 结构化绑定

利用该特性可以把以 C++ 中的 pair,tuple,array,struct 的成员赋值给多个变量。

C++

#include <iostream>
#include <tuple>

struct Point {
    int x;
    int y;
    Point(int x, int y) {
        this->x = x;
        this->y = y;
    }
};

int main() {
    auto [x, y, z] = std::make_tuple(1, 2.3, "456");
    auto [a, b] = std::make_pair(1, 2);
    int arr[3] = {1, 2, 3};
    auto [c, d, e] = arr;
    auto [f, g] = Point(5, 6);
    return 0;
}
  • if-switch 语句初始化:

if 语句可以支持 if (init; condition) 写法,即在判断条件中对变量进行初始化。

C++

if (int a = 10; a < 101) {
    cout << a;
}
  • constexpr lambda 表达式:

C++ 17 前 lambda 表达式只能在运行时使用,C++ 17 引入了 constexpr lambda 表达式,可以用于在编译期进行计算。

C++

int main() {
    constexpr auto lamb = [] (int n) { return n * n; };
    static_assert(lamb(3) == 9, "a");
}
  • namespace 嵌套:

C++ 17 支持命名空间嵌套,比如如下写法:

C++

#include <iostream>
namespace A {
    void func(){
        std::cout<<"A func"<<std::endl;
    }
    namespace B {
        namespace C {
            void func(){
                std::cout<<"C func"<<std::endl;
            }
        }
    }
}

int main(int argc, char * argv[])
{
    A::func(); // A func 
    A::B::C::func(); // C func
    return 0;
}
  • std::any:

增加了 any 可以存储任何类型,可以将其转化为任意类型。

C++

std::any t = 100;
cout << std::any_cast<int>(t) << endl;
t.reset();
t = std::string("1111111");
cout << std::any_cast<string>(t) << endl;
  • std::basic_string_view:

字符串视图实际为对外部字符串或字符串片断(string-slice)的引用。通过 string view 可以访问字符串,但不允许修改字符串。它并不真正持有这个字符串的拷贝,而是与相对应的字符串共享同一段空间。string view 的创建与修改不影响原始字符串。string_view 支持迭代器,也同样支持 for 语句获取元素等操作,标准库也为它编写了相关的 istream 和 ostream 的运算符重载形式,同时也支持字符串查找操作。

C++

string s = "123456789";
std::string_view sv(s.c_str());
cout<<sv<<endl;
for (auto & ch : sv) {
    cout << ch << ' ';
}
for (auto it = sv.crbegin(); it != sv.crend(); ++it) {
    cout << *it << ' ';
}
cout<<sv.find("345")<<endl; // 2

string_view 并不真正的持有字符串,所以若视图所引用的字符串区域已经被销毁,那么对应的,视图也会相应的失效。

C++

std::string_view test() {
    char str[] = "1111111";
    return {str};
}

int main() {
    cout<< test() << endl; // error
    return 0;
}
  • std::filesystem:

C++ 17 正式将 filesystem 纳入标准中,提供了关于文件的大多数功能。

阅读量:2017

点赞量:0

收藏量:0