C++20新特性解析

嵌入式技术

1368人已加入

描述

C++之父都说过,C++20是C++语言的一次重大变革,引入了大量的新特性。

代码

这其中个人认为最重要新特性是这三个:

  • Modules

  • Coroutines

  • Concepts

Modules

直接看代码:

// helloworld.cpp
export module helloworld;  // module declaration
import ;         // import declaration
export void hello() {      // export declaration
    std::cout << "Hello world!
";
}

	

 

// main.cppimport helloworld;  // import declaration
int main() {
    hello();
}

	

每个C++开发者应该都知道include方式是将header中的代码拷贝一份到源文件中,在大的工程项目中还有很多冗余的include,种种原因,导致编译速度相当的慢,而modules却大大改善了这种问题。

modules使用方式和include差不多,但modules使用比include头文件速度更快,C++全球开发者大会中,C++之父贴出来过测试数据,modules效率比include高了25倍。

代码

以后modules肯定会是主流使用方式。

Coroutines

协程是一种比线程和进程更高效的多任务处理模型。

在C++20中,终于把协程引了进来,协程具体还分为有栈协程和无栈协程,两者对比,无栈协程是更高效的协程。

而C++20支持的就是无栈协程,为此提供了三个关键字:

  • co_await:暂停执行,直到恢复

  • co_yield:暂停执行,返回一个值

  • co_return:完成执行,返回一个值

 

这是一段cppreference上,协程相关的示例代码:


	
#include #include #include #include 
auto switch_to_new_thread(std::jthread& out) {
  struct awaitable {
    std::jthread* p_out;
    bool await_ready() { return false; }
    void await_suspend(std::coroutine_handle<> h) {
      std::jthread& out = *p_out;
      if (out.joinable())
        throw std::runtime_error("Output jthread parameter not empty");
      out = std::jthread([h] { h.resume(); });
      // Potential undefined behavior: accessing potentially destroyed *this
      // std::cout << "New thread ID: " << p_out->get_id() << '
';
      std::cout << "New thread ID: " << out.get_id() << '
'; // this is OK
    }
    void await_resume() {}
  };
  return awaitable{&out};
}


struct task{
  struct promise_type {
    task get_return_object() { return {}; }
    std::suspend_never initial_suspend() { return {}; }
    std::suspend_never final_suspend() noexcept { return {}; }
    void return_void() {}
    void unhandled_exception() {}
  };
};


task resuming_on_new_thread(std::jthread& out) {
  std::cout << "Coroutine started on thread: " << std::get_id() << '
';
  co_await switch_to_new_thread(out);
  // awaiter destroyed here
  std::cout << "Coroutine resumed on thread: " << std::get_id() << '
';
}


int main() {
  std::jthread out;
  resuming_on_new_thread(out);
}

	

目前C++20只是从语法层面对协程做了支持,还没有相关的协程库,要想使用协程,还需要引入协程库,但不可否认,C++20已经支持了协程,以后在这方面肯定会越来越完善。

前一段时间参加的C++全球开发者大会,C++之父也说过会全力在C++23标准中引入对协程库的支持。

代码

Concepts

Concepts在模板编程中起到重大的作用, 类模板、函数模板和非模板函数(通常是类模板的成员)可以与一个约束相关联,这个约束指定了对模板实参的要求,这些实参可用于选择最合适的函数重载和模板特化。

很多人应该都知道SFINAE,在C++20前多数都在使用std::enable_if,这相当的麻烦,代码可读性也不高,编译器报错信息也不是很友好,而有了Concepts就方便的多, 每个Concepts都是一个谓词,在编译时计算,并成为模板接口的一部分,在那里它被用作约束:

#include #include #include 
template<typename T>
concept Hashable = requires(T a) {
    { std::hash{}(a) } -> std::convertible_to<std::size_t>;
};
struct meow {};
// Constrained C++20 function template:
template
void f(T) {}


int main() {
  using std::operator""s;
  f("abc"s); // OK, std::string satisfies Hashable
  //f(meow{}); // Error: meow does not satisfy Hashable
}

	

其实C++20还有一些特性我比较喜欢,比如std::jthread,真真切切的解决了std::thread存在的旧有问题。

还有fmt,因为cout方式输出复杂的格式很麻烦:比如我想输出a + b = c:

std::cout << a << " + " << b << " = " << c << std::endl;

	

是不是很麻烦,那可以使用printf?

printf("%d + %d = %d 
", a, b, c);

	

但printf需要开发者填入变量格式,如果填写有误,有可能打印错误,也有可能crash

  • 某个long long 型,使用%d打印会怎么样?

  • 某个int32_t型,使用%lld打印会怎么样?

  • 某个const char* 型,使用%d打印会怎么样?

  • 某个float型,使用%d打印会怎么样?

 

所以使用printf会给开发者带来负担,一定要在打印前确认变量的类型,并且一定要保证配置的输出格式正确,我想大多数人可能都会在print某个变量前搜索过打印某个类型需要使用哪种格式吧

那用啥呢?cout配合format

std::cout << std::format("{} + {} = {} 
", a, b, c);

	

C++20其实还有很多有意思的新特性,而这些特性在这本书中都有详细的介绍,大家感兴趣可以看看。

 

  审核编辑:汤梓红
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分