c++高级用法

1|0lambda函数的两种用法

  • lambda标准语法

  • auto

auto factorial = [](auto self, int n) -> int { return n < 2 ? 1 : n * self(self, n - 1); };
  • function
std::function<void(int, int)> dfs = [&](int i, int j) { if (mask_.at<uchar>(i, j) == 255) return; mask_.at<uchar>(i, j) = 255; for (int k = 0; k < 4; ++k) { int ii = i + ff[k][0], jj = j + ff[k][1]; if (ii < m.rows && jj < m.cols) dfs(ii, jj); } };
  • 如果文件存在,删除文件
#ifdef _WIN32 #include <io.h> #include <cstdio> #endif #ifdef linux #include <unistd.h> #include <fcntl.h> #endif void delete_file(std::string strFileName){ #ifdef linux if (access(strFileName.c_str(), F_OK) == 0) remove(strFileName.c_str()); #endif #ifdef _WIN32 if (_access(strFileName.c_str(), 0) == 0) remove(strFileName.c_str()); #endif }

2|0goto

  • a的值等于15时,程序会跳过迭代并继续执行下一次循环
LOOP:do { if( a == 15) { // 跳过迭代 a = a + 1; goto LOOP; }

3|0其他编译单元就可以直接调用

__attribute__((visibility("default")))

4|0测试

boost.cpp

#include <boost/test/included/unit_test.hpp> #include "need2test.h" #include "need2test2.h"

need2test.h

#define BOOST_TEST_MODULE MyTestModule BOOST_AUTO_TEST_SUITE(MyTestSuite) BOOST_AUTO_TEST_CASE(MyTestCase1) { BOOST_CHECK(1 + 1 == 2); } BOOST_AUTO_TEST_CASE(MyTestCase2) { BOOST_CHECK(2 * 2 == 4); } BOOST_AUTO_TEST_SUITE_END()

5|0-std=c++11

禁止对象的拷贝与赋值delete

struct A { A() = default; A(const A&) = delete; A& operator=(const A&) = delete; int a; A(int i) { a = i; } }; int main() { A a1; A a2 = a1; // 错误,拷贝构造函数被禁用 A a3; a3 = a1; // 错误,拷贝赋值操作符被禁用 }

6|0-std=c++14

C++14引入了二进制字面量,也引入了分隔符

int a = 0b0001'0011'1010; double b = 3.14'1234'1234'1234;

std::make_unique

struct A {}; std::unique_ptr<A> ptr = std::make_unique<A>();

多读、单写锁

struct ThreadSafe { mutable std::shared_timed_mutex mutex_; int value_; ThreadSafe() { value_ = 0; } int get() const { std::shared_lock<std::shared_timed_mutex> loc(mutex_); return value_; } void increase() { std::unique_lock<std::shared_timed_mutex> lock(mutex_); value_ += 1; } };

std::exchange比swap更高效

std::vector<int> v; std::exchange(v, {1,2,3,4});

std::quoted 给字符串添加双引号

cout << std::quoted(str) << endl; "hello world"

inline
允许同一个函数或变量的定义出现在多个编译单元中

//a.h inline void func(); //b.h #include "a.h" inline void func();

7|0-std=c++17

构造函数模板推导

pair<int, double> p(1, 2.2); // before c++17 pair p(1, 2.2); // c++17 自动推导 vector v = {1, 2, 3}; // c++17

结构化绑定

std::tuple<int, double> func() { return std::tuple(1, 2.2); } int main() { auto[i, d] = func(); //是C++11的tie吗?更高级 cout << i << endl; cout << d << endl; }

折叠表达式

template <typename ... Ts> auto sum(Ts ... ts) { return (ts + ...); } int a {sum(1, 2, 3, 4, 5)}; // 15 std::string a{"hello "}; std::string b{"world"}; cout << sum(a, b) << endl; // hello world

C++17引入了constexpr lambda表达式,可以用于在编译期进行计算。
有以下限制
函数体不能包含汇编语句goto语句、label、try块、静态变量、线程局部存储、
没有初始化的普通变量,不能动态分配内存,不能有new delete等,
不能虚函数

int main() { // c++17可编译 constexpr auto lamb = [] (int n) { return n * n; }; static_assert(lamb(3) == 9, "a"); }

namespace嵌套

namespace A { namespace B { namespace C { void func(); } } } // c++17,更方便更舒适 namespace A::B::C { void func();) }

__has_include预处理表达式

#if defined __has_include #if __has_include(<charconv>) #define has_charconv 1 #include <charconv> #endif #endif std::optional<int> ConvertToInt(const std::string& str) { int value{}; #ifdef has_charconv const auto last = str.data() + str.size(); const auto res = std::from_chars(str.data(), last, value); if (res.ec == std::errc{} && res.ptr == last) return value; #else // alternative implementation... 其它方式实现 #endif return std::nullopt; }

std::variant
类似union的功能,但比union更高级

int main() { // c++17可编译 std::variant<int, std::string> var("hello"); cout << var.index() << endl; var = 123; cout << var.index() << endl; try { var = "world"; std::string str = std::get<std::string>(var); // 通过类型获取值 var = 3; int i = std::get<0>(var); // 通过index获取对应值 cout << str << endl; cout << i << endl; } catch(...) { // xxx; } return 0; }

std::optional

  • 让函数返回对象指针,异常情况下返回nullptr
std::optional<int> StoI(const std::string &s) { try { return std::stoi(s); } catch(...) { return std::nullopt; } } void func() { std::string s{"123"}; std::optional<int> o = StoI(s); if (o) { cout << *o << endl; } else { cout << "error" << endl; } }

std::any
C++17引入了any可以存储任何类型的单个值

int main() { // c++17可编译 std::any a = 1; cout << a.type().name() << " " << std::any_cast<int>(a) << endl; a = 2.2f; cout << a.type().name() << " " << std::any_cast<float>(a) << endl; if (a.has_value()) { cout << a.type().name(); } a.reset(); if (a.has_value()) { cout << a.type().name(); } a = std::string("a"); cout << a.type().name() << " " << std::any_cast<std::string>(a) << endl; return 0; }

std::string_view

if-switch语句初始化

// if (init; condition) if (int a = GetValue()); a < 101) { cout << a; } string str = "Hi World"; if (auto [pos, size] = pair(str.find("Hi"), str.size()); pos != string::npos) { std::cout << pos << " Hello, size is " << size; }

折叠表达式

template <typename ... Ts> auto sum(Ts ... ts) { return (ts + ...); } int a {sum(1, 2, 3, 4, 5)}; // 15 std::string a{"hello "}; std::string b{"world"}; cout << sum(a, b) << endl; // hello world

新增Attribute

  • [[fallthrough]],用在switch中提示可以直接落下去,不需要break,让编译期忽略警告
  • [[nodiscard]] :表示修饰的内容不能被忽略,可用于修饰函数,标明返回值一定要被处理
  • [[maybe_unused]] :提示编译器修饰的内容可能暂时没有使用,避免产生警告

C++17使用as_const可以将左值转成const类型

std::string str = "str"; const std::string& constStr = std::as_const(str);

8|0-std=c++20

默认生成一系列的比较运算符
即:==,!=,<,>,<=,>=
自定义时有三种可用的返回类型:

  • std::strong_ordering:强比较,严格按照比较的顺序、方式来进行,不能从下面两个转回,特别注意的是它不区分等价值。
  • std::weak_ordering:弱比较,对比较的大小写,可以对等价的字符串用某种方式区别
  • std::partial_ordering:偏序比较,其实就是自定义,把直观上不可能比较的对象通过某种方式来进行比较
auto operator<=>(const Point&) const = default; class TotallyOrdered : Base { std::string tax_id; std::string first_name; std::string last_name; public: TotallyOrdered(const std::string& id, const std::string& first, const std::string& last) :tax_id(id), first_name(first), last_name(last) {} // 定制 operator<=>,因为我们想先比较姓 std::strong_ordering operator<=>(const TotallyOrdered& that) const { if (auto cmp = (Base&)(*this) <=> (Base&)that; cmp != 0) return cmp; if (auto cmp = last_name <=> that.last_name; cmp != 0) return cmp; if (auto cmp = first_name <=> that.first_name; cmp != 0) return cmp; return tax_id <=> that.tax_id; } // ……非比较函数…… }; constexpr std::weak_ordering operator<=>(Rational_2 lhs, Rational_2 rhs) { return lhs.num * rhs.den <=> rhs.num * lhs.den; }

9|0模板

  • 可以使用省略号运算符 (...) 定义采用任意数量的零个或多个类型参数的模板:
template<typename... Arguments> class vtclass; vtclass< > vtinstance1; vtclass<int> vtinstance2; vtclass<float, bool> vtinstance3;
  • C++ 模板支持非类型参数,也称为值参数
    • size_t 值在编译时作为模板参数传入,必须是 const 或 constexpr 表达式。
template<typename T, size_t L> class MyArray { T arr[L]; public: MyArray() { ... } }; MyArray<MyClass*, 10> arr;
  • 模板作为模板参数
template<typename T, template<typename, int> class Arr> class MyClass2 { T t; //OK Arr<T, 10> a; };
  • 默认模板自变量
template<typename A = int, typename B = double> class Bar { //... }; ... int main() { Bar<> bar; // use all default type arguments }
  • 例如,std::vector 模板有一个用于分配器的默认自变量:
template <class T, class Allocator = allocator<T>> class vector;

__EOF__

本文作者InsiApple
本文链接https://www.cnblogs.com/InsiApple/p/17295397.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   InsiApple  阅读(109)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示