c++新特性- 个人总结

C++11的新特性

这里就不详细罗列了,只是说特性有哪些

1️⃣ auto(类型推导)

2️⃣ nullptr(干掉 NULL)

3️⃣ 智能指针(核心中的核心)

4️⃣ lambda 表达式

5️⃣ range-for (for-each)

6️⃣ move 语义 & 右值引用(性能关键)

C++14 (C++11补丁版)

1️⃣ auto 返回值

复制代码
auto add(int a, int b) {
    return a + b;
}

📌 工程价值

  • 泛型函数更自然

2️⃣ lambda 支持 auto 参数

复制代码
auto lambda = [](auto a, auto b) {
    return a + b;
};

lambda(1, 2);
lambda(1.5, 2.3);

📌 工程价值

  • 泛型算法写起来像脚本

C++17新特性

结构化绑定

定义

structured bindings(结构化绑定)

复制代码
std::map<int, std::string> m;

for (auto& [key, value] : m) {
    std::cout << key << value;
}

📌 工程价值

  • 遍历 map 不再 first / second
  • 代码可读性爆炸提升
用例

从元组/结构体解包 到 变量上面

auto [x, y] = std::pair{1, 2.0};

c 复制代码
#include <iostream>
#include <tuple>
#include <map>
#include <string>

// 定义:从元组、数组或结构体中将多个变量绑定到成员

// 示例1:从pair解包 到对应的变量上面
void example_pair() {
    std::pair<int, double> p{42, 3.14};
    auto [x, y] = p;  // x=42, y=3.14
    std::cout << "x=" << x << ", y=" << y << std::endl;
}

// 示例2:从tuple解包 到对应的变量上面
void example_tuple() {
    auto t = std::make_tuple(1, "hello", 4.5);
    auto [a, b, c] = t;  // a=1, b="hello", c=4.5
    std::cout << "a=" << a << ", b=" << b << ", c=" << c << std::endl;
}

// 示例3:从数组解包 到对应的变量上面
void example_array() {
    int arr[3] = {10, 20, 30};
    auto [first, second, third] = arr;  // 数组大小必须匹配
    std::cout << first << " " << second << " " << third << std::endl;
}

// 示例4:从结构体解包 到对应的变量上面
struct Point {
    int x;
    int y;
    std::string name;
};

void example_struct() {
    Point p{100, 200, "origin"};
    auto [x_coord, y_coord, point_name] = p;
    std::cout << point_name << ": (" << x_coord << ", " << y_coord << ")\n";
}

// 示例5:在循环中使用 到对应的变量上面
void example_loop() {
    std::map<int, std::string> m = {
        {1, "one"},
        {2, "two"},
        {3, "three"}
    };
    
    // 传统方式
    for (const auto& kv : m) {
        std::cout << kv.first << ": " << kv.second << std::endl;
    }
    
    // 使用结构化绑定
    for (const auto& [key, value] : m) {
        std::cout << key << ": " << value << std::endl;
    }
}

// 示例6:使用引用
void example_reference() {
    std::pair<int, std::string> p{1, "test"};
    auto& [num, str] = p;  // 使用引用,修改会影响原值
    num = 100;
    std::cout << p.first << std::endl;  // 输出100
}

int main() {
    example_pair();
    example_tuple();
    example_array();
    example_struct();
    example_loop();
    example_reference();
    return 0;
}

if/switch 初始化语句

定义

if / switch 初始化语句 ⭐⭐⭐⭐⭐

复制代码
if (auto it = map.find(key); it != map.end()) {
    std::cout << it->second;
}

📌 工程价值

  • 变量作用域最小化
  • 写 UI / 状态判断特别干净
用例
c 复制代码
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <mutex>
#include <memory>

// 定义:在if/switch条件中初始化变量,变量作用域限于条件语句块

// 示例1:基本用法
void example_basic() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
    
    // 传统方式
    {
        auto it = m.find(1);
        if (it != m.end()) {
            std::cout << "Found: " << it->second << std::endl;
        }
    }
    
    // C++17方式:更简洁,it作用域限于if语句
    if (auto it = m.find(1); it != m.end()) {
        std::cout << "Found: " << it->second << std::endl;
    }
    // it在这里不可访问
    
    // 可以使用else if
    if (auto it = m.find(3); it != m.end()) {
        std::cout << "Found: " << it->second << std::endl;
    } else {
        std::cout << "Not found" << std::endl;
    }
}

// 示例2:锁的获取和检查
void example_lock() {
    std::mutex mtx;
    std::vector<int> shared_data;
    
    // 传统方式
    {
        std::lock_guard<std::mutex> lock(mtx);
        if (!shared_data.empty()) {
            std::cout << "Data size: " << shared_data.size() << std::endl;
        }
    }
    
    // C++17方式:锁的作用域明确
    if (std::lock_guard<std::mutex> lock(mtx); !shared_data.empty()) {
        std::cout << "Data size: " << shared_data.size() << std::endl;
    }
}

// 示例3:资源管理
void example_resource() {
    // 传统方式:需要额外的{}限制作用域
    {
        std::unique_ptr<int> ptr = std::make_unique<int>(42);
        if (ptr) {
            std::cout << *ptr << std::endl;
        }
    }
    
    // C++17方式
    if (auto ptr = std::make_unique<int>(42); ptr) {
        std::cout << *ptr << std::endl;
    }
    // ptr已自动释放
}

// 示例4:switch中的初始化
void example_switch(int value) {
    // 传统方式
    {
        auto result = value * 2;
        switch (result) {
            case 2: std::cout << "Two"; break;
            default: std::cout << "Other"; break;
        }
    }
    
    // C++17方式
    switch (auto result = value * 2; result) {
        case 2:
            std::cout << "Two";
            break;
        case 4:
            std::cout << "Four";
            break;
        default:
            std::cout << "Other: " << result;
            break;
    }
}

// 示例5:类型检查和转换
void example_type_check() {
    class Base { public: virtual ~Base() = default; };
    class Derived : public Base { public: void specific() {} };
    
    Base* base_ptr = new Derived();
    
    // 传统方式
    {
        Derived* derived = dynamic_cast<Derived*>(base_ptr);
        if (derived) {
            derived->specific();
        }
    }
    
    // C++17方式
    if (Derived* derived = dynamic_cast<Derived*>(base_ptr); derived) {
        derived->specific();
    }
    
    delete base_ptr;
}

// 示例6:错误处理
#include <system_error>
#include <fstream>

void example_error_handling() {
    // 文件操作中的错误检查
    if (std::ifstream file{"data.txt"}; file.is_open()) {
        std::string content;
        std::getline(file, content);
        std::cout << "Content: " << content << std::endl;
    } else {
        std::cout << "Failed to open file" << std::endl;
    }
}

// 示例7:多重条件
void example_multi_condition() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    
    // 传统方式
    {
        auto it = std::find(vec.begin(), vec.end(), 3);
        if (it != vec.end() && *it > 2) {
            std::cout << "Found and value > 2" << std::endl;
        }
    }
    
    // C++17方式
    if (auto it = std::find(vec.begin(), vec.end(), 3); 
        it != vec.end() && *it > 2) {
        std::cout << "Found and value > 2" << std::endl;
    }
}

int main() {
    example_basic();
    example_lock();
    example_resource();
    example_switch(2);
    example_type_check();
    example_error_handling();
    example_multi_condition();
    return 0;
}

constexpr if - 编译期条件判断

c 复制代码
#include <iostream>
#include <type_traits>
#include <vector>
#include <string>

// 定义:在编译期进行条件判断,未选中的分支不会实例化

// 示例1:基本用法
template<typename T>
auto get_value(T t) {
    // 编译期判断T是否为指针类型
    if constexpr (std::is_pointer_v<T>) {
        std::cout << "Pointer: ";
        return *t;  // 解引用
    } else {
        std::cout << "Value: ";
        return t;   // 直接返回
    }
}

void example_basic() {
    int x = 42;
    int* ptr = &x;
    
    std::cout << get_value(x) << std::endl;    // 输出: Value: 42
    std::cout << get_value(ptr) << std::endl;  // 输出: Pointer: 42
}

// 示例2:处理不同类型
template<typename T>
void process(T value) {
    if constexpr (std::is_integral_v<T>) {
        std::cout << "Integral: " << value * 2 << std::endl;
    } else if constexpr (std::is_floating_point_v<T>) {
        std::cout << "Floating: " << value * 1.5 << std::endl;
    } else if constexpr (std::is_pointer_v<T>) {
        std::cout << "Pointer to: " << *value << std::endl;
    } else {
        std::cout << "Other type" << std::endl;
    }
}

// 示例3:元编程 - 编译期计算
template<int N>
constexpr int factorial() {
    if constexpr (N <= 1) {
        return 1;
    } else {
        return N * factorial<N - 1>();
    }
}

// 示例4:处理不同容器的迭代
template<typename Container>
void print_container(const Container& container) {
    if constexpr (std::is_same_v<Container, std::string>) {
        // 字符串特殊处理
        std::cout << "String: " << container << std::endl;
    } else {
        // 其他容器通用处理
        std::cout << "Container elements: ";
        for (const auto& elem : container) {
            std::cout << elem << " ";
        }
        std::cout << std::endl;
    }
}

// 示例5:SFINAE的现代替代
template<typename T, typename = void>
struct has_size_method : std::false_type {};

template<typename T>
struct has_size_method<T, std::void_t<decltype(std::declval<T>().size())>> 
    : std::true_type {};

template<typename T>
void check_size(const T& obj) {
    if constexpr (has_size_method<T>::value) {
        std::cout << "Has size: " << obj.size() << std::endl;
    } else {
        std::cout << "No size method" << std::endl;
    }
}

// 示例6:类型特化
template<typename T>
class MyClass {
public:
    void process() {
        if constexpr (std::is_same_v<T, int>) {
            std::cout << "Processing int type" << std::endl;
            // 只能用于int的代码
        } else if constexpr (std::is_same_v<T, double>) {
            std::cout << "Processing double type" << std::endl;
            // 只能用于double的代码
        } else {
            std::cout << "Processing generic type" << std::endl;
        }
    }
};

// 示例7:编译期字符串处理
template<typename T>
constexpr auto type_name() {
    if constexpr (std::is_same_v<T, int>) {
        return "int";
    } else if constexpr (std::is_same_v<T, double>) {
        return "double";
    } else if constexpr (std::is_same_v<T, std::string>) {
        return "std::string";
    } else {
        return "unknown";
    }
}

// 示例8:错误处理
template<typename T>
T parse_string(const std::string& str) {
    if constexpr (std::is_same_v<T, int>) {
        return std::stoi(str);
    } else if constexpr (std::is_same_v<T, double>) {
        return std::stod(str);
    } else if constexpr (std::is_same_v<T, float>) {
        return std::stof(str);
    } else {
        static_assert(false, "Unsupported type for parsing");
    }
}

// 示例9:递归模板终止条件
template<int N>
struct Fibonacci {
    static constexpr int value = []() {
        if constexpr (N <= 1) {
            return N;
        } else {
            return Fibonacci<N - 1>::value + Fibonacci<N - 2>::value;
        }
    }();
};

// 示例10:编译期与运行时结合
template<typename Func>
auto measure_time(Func&& func) {
    if constexpr (std::is_same_v<decltype(func()), void>) {
        // 返回void的函数
        auto start = std::chrono::high_resolution_clock::now();
        func();
        auto end = std::chrono::high_resolution_clock::now();
        return end - start;
    } else {
        // 有返回值的函数
        auto start = std::chrono::high_resolution_clock::now();
        auto result = func();
        auto end = std::chrono::high_resolution_clock::now();
        return std::make_pair(result, end - start);
    }
}

int main() {
    example_basic();
    
    process(10);           // Integral
    process(3.14);         // Floating
    int y = 5;
    process(&y);           // Pointer
    
    std::cout << "Factorial of 5: " << factorial<5>() << std::endl;
    
    std::string str = "hello";
    std::vector<int> vec = {1, 2, 3};
    print_container(str);  // String处理
    print_container(vec);  // 容器处理
    
    check_size(str);       // Has size
    check_size(10);        // No size method
    
    MyClass<int> int_obj;
    MyClass<double> double_obj;
    MyClass<std::string> str_obj;
    int_obj.process();
    double_obj.process();
    str_obj.process();
    
    std::cout << "Type: " << type_name<int>() << std::endl;
    std::cout << "Type: " << type_name<std::string>() << std::endl;
    
    std::cout << "Fibonacci(10): " << Fibonacci<10>::value << std::endl;
    
    return 0;
}

std::optional 详细用法

c 复制代码
#include <iostream>
#include <optional>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>

// 定义:表示一个可能存在也可能不存在的值,替代使用特殊值表示"无值"

// 示例1:基本创建和访问
void example_basic() {
    // 创建有值的optional
    std::optional<int> opt1 = 42;
    std::optional<std::string> opt2 = "hello";
    std::optional<double> opt3 = 3.14;
    
    // 创建空optional
    std::optional<int> empty_opt;
    std::optional<int> empty_opt2 = std::nullopt;
    
    // 检查是否有值
    if (opt1.has_value()) {
        std::cout << "opt1 has value: " << opt1.value() << std::endl;
    }
    
    // 使用bool转换检查
    if (opt2) {
        std::cout << "opt2 has value: " << *opt2 << std::endl;
    }
    
    // 安全访问(推荐)
    if (opt3) {
        std::cout << "opt3 value: " << opt3.value() << std::endl;
    }
    
    // 不安全访问(可能抛出异常)
    try {
        std::cout << "Empty opt: " << empty_opt.value() << std::endl;
    } catch (const std::bad_optional_access& e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }
}

// 示例2:作为函数返回值
std::optional<int> find_value(const std::vector<int>& vec, int target) {
    auto it = std::find(vec.begin(), vec.end(), target);
    if (it != vec.end()) {
        return *it;  // 找到,返回值
    }
    return std::nullopt;  // 没找到,返回空
}

std::optional<std::string> parse_number(int num) {
    if (num >= 0 && num <= 9) {
        return std::to_string(num);
    }
    return std::nullopt;
}

void example_function_return() {
    std::vector<int> numbers = {1, 3, 5, 7, 9};
    
    // 使用返回值
    auto result = find_value(numbers, 5);
    if (result) {
        std::cout << "Found: " << *result << std::endl;
    }
    
    // 使用value_or提供默认值
    auto not_found = find_value(numbers, 2);
    std::cout << "Value or default: " 
              << not_found.value_or(-1) << std::endl;  // 输出-1
}

// 示例3:处理复杂类型
class User {
public:
    std::string name;
    int age;
    
    User(std::string n, int a) : name(std::move(n)), age(a) {}
    
    void print() const {
        std::cout << "User: " << name << ", Age: " << age << std::endl;
    }
};

std::optional<User> find_user(const std::string& name) {
    if (name == "Alice") {
        return User{"Alice", 30};
    } else if (name == "Bob") {
        return User{"Bob", 25};
    }
    return std::nullopt;
}

// 示例4:optional的链式操作
struct Connection {
    std::optional<std::string> send_request() {
        return "response";
    }
};

std::optional<Connection> connect() {
    return Connection{};
}

std::optional<std::string> parse_response(const std::string& resp) {
    if (!resp.empty()) {
        return "parsed: " + resp;
    }
    return std::nullopt;
}

void example_chaining() {
    // 传统方式
    {
        auto conn_opt = connect();
        if (conn_opt) {
            auto resp_opt = conn_opt->send_request();
            if (resp_opt) {
                auto parsed_opt = parse_response(*resp_opt);
                if (parsed_opt) {
                    std::cout << *parsed_opt << std::endl;
                }
            }
        }
    }
    
    // 使用and_then实现链式调用
    auto result = connect()
        .and_then([](Connection& conn) { return conn.send_request(); })
        .and_then(parse_response);
    
    if (result) {
        std::cout << "Chained result: " << *result << std::endl;
    }
}

// 示例5:与标准算法结合
void example_with_algorithms() {
    std::vector<std::optional<int>> opts = {
        1, std::nullopt, 3, std::nullopt, 5
    };
    
    // 过滤掉空值
    std::vector<int> values;
    for (const auto& opt : opts) {
        if (opt) {
            values.push_back(*opt);
        }
    }
    
    // 使用transform
    std::vector<std::optional<int>> transformed;
    std::transform(opts.begin(), opts.end(), 
                   std::back_inserter(transformed),
                   [](const auto& opt) -> std::optional<int> {
                       if (opt) {
                           return *opt * 2;
                       }
                       return std::nullopt;
                   });
}

// 示例6:性能优化 - 延迟初始化
class ExpensiveResource {
    std::optional<std::vector<int>> cache;
    
public:
    const std::vector<int>& get_data() {
        if (!cache) {
            // 延迟初始化
            cache = std::vector<int>{1, 2, 3, 4, 5};
            std::cout << "Initialized cache" << std::endl;
        }
        return *cache;
    }
    
    void clear_cache() {
        cache.reset();
    }
};

// 示例7:错误处理的替代方案
enum class ErrorCode {
    OK,
    NOT_FOUND,
    INVALID_INPUT,
    TIMEOUT
};

std::optional<std::string> fetch_data(ErrorCode& error) {
    // 传统方式:通过输出参数返回错误
    error = ErrorCode::OK;
    return "data";
}

std::optional<std::string> fetch_data_modern() {
    // 使用optional:要么返回数据,要么返回空
    return "data";
    // 或者 return std::nullopt; 表示错误
}

// 示例8:与variant结合
#include <variant>

using Result = std::variant<std::string, std::nullopt_t>;

Result process_data() {
    bool success = true; // 模拟操作结果
    if (success) {
        return "success data";
    }
    return std::nullopt;
}

// 示例9:optional的引用
void process_if_present(const std::optional<std::string>& opt) {
    // optional可以包含引用语义
    if (opt) {
        std::cout << "Processing: " << *opt << std::endl;
    }
}

// 示例10:自定义类型的optional
class Config {
    std::optional<std::string> theme;
    std::optional<int> timeout;
    std::optional<bool> debug_mode;
    
public:
    void set_theme(const std::string& t) { theme = t; }
    void set_timeout(int t) { timeout = t; }
    
    std::string get_theme() const { return theme.value_or("default"); }
    int get_timeout() const { return timeout.value_or(30); }
    
    void print() const {
        std::cout << "Theme: " << get_theme() 
                  << ", Timeout: " << get_timeout() << std::endl;
    }
};

int main() {
    example_basic();
    example_function_return();
    
    // 用户查找示例
    auto user = find_user("Alice");
    if (user) {
        user->print();
    }
    
    // 延迟初始化示例
    ExpensiveResource resource;
    auto& data = resource.get_data();  // 第一次调用会初始化
    auto& data2 = resource.get_data(); // 使用缓存
    
    // 配置示例
    Config config;
    config.print();  // 使用默认值
    
    config.set_theme("dark");
    config.set_timeout(60);
    config.print();  // 使用设置的值
    
    return 0;
}

std::variant 详细用法

定义

std::variant(类型安全 union)

复制代码
std::variant<int, double, std::string> v;

v = 10;
v = "hello";

std::visit([](auto&& arg) {
    std::cout << arg;
}, v);

📌 工程价值

  • 状态机
  • 不同类型结果统一返回

std::visit

c++ 复制代码
std::variant<int, double, std::string> v = "world";

std::visit([](auto&& arg) {
    using T = std::decay_t<decltype(arg)>;

    if constexpr (std::is_same_v<T, int>) {
        std::cout << "int: " << arg * 2 << std::endl;
    }
    else if constexpr (std::is_same_v<T, double>) {
        std::cout << "double: " << arg + 0.5 << std::endl;
    }
    else if constexpr (std::is_same_v<T, std::string>) {
        std::cout << "string length: " << arg.size() << std::endl;
    }
}, v);
  • variant 当前持有哪种类型
  • visit 自动调用 lambda
  • arg 的真实类型在 编译期确定

📌 零运行时 RTTI / 零 dynamic_cast

多个variant一起使用的话

c 复制代码
std::variant<int, double> a = 3;
std::variant<int, double> b = 4.5;

std::visit([](auto x, auto y) {
    std::cout << x + y << std::endl;
}, a, b);
// 编译期展开

std::decay_t<> 作用

在上面的例子当中:

c 复制代码
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, int>) {
 std::cout << "int: " << arg * 2 << std::endl;
}

先从 decltype(arg) 说起

1️⃣ decltype(arg) 是什么?

复制代码
auto&& arg = ...;
decltype(arg)

decltype(arg) 不是你以为的类型

假设:

复制代码
int x = 10;
auto&& arg = x;

那么:

复制代码
decltype(arg)  // 是:int&

如果:

复制代码
const int y = 20;
auto&& arg = y;

那么:

复制代码
decltype(arg)  // 是:const int&

📌 结论 :decltype(arg) 会保留:1、引用(& / &&); 2、const / volatile

二、那 std::decay_t 是干嘛的? 2️⃣ std::decay<T> 做了什么?

std::decay<T>"函数参数退化规则"

它会帮你:

原类型 decay 后
int& int
const int& int
int&& int
const int int
T[N] T*
T() T(*)()

📌 核心作用

👉 去引用 + 去 const

三、合起来看:std::decay_t<decltype(arg)>

拆解顺序

复制代码
decltype(arg)          // 带引用、带 const
std::decay_t<...>      // 去掉引用和 const

实际例子(非常关键)

复制代码
std::visit([](auto&& arg) {
    using T = std::decay_t<decltype(arg)>;

    // T 是一个"干净类型"
}, v);

如果 variant 当前是:

variant 内类型 arg 实际类型 T 最终类型
int int& int
double double& double
std::string std::string& std::string

四、为什么不能直接用 decltype(arg)

❌ 错误写法

复制代码
if constexpr (std::is_same_v<decltype(arg), int>) {
    ...
}

几乎永远不成立

因为 decltype(arg) 是:

  • int&
  • const int&

而你拿它去和 int 比,当然不相等。

五、正确写法对比(必背)

✅ 写法 1(最常见)

复制代码
using T = std::decay_t<decltype(arg)>;

if constexpr (std::is_same_v<T, int>) {
    ...
}
具体用例
c 复制代码
#include <iostream>
#include <variant>
#include <string>
#include <vector>
#include <type_traits>
#include <cassert>

// 定义:类型安全的联合体,可以持有多种类型中的一种

// 示例1:基本创建和访问
void example_basic() {
    // 创建variant,可以持有int, double或string
    std::variant<int, double, std::string> v;
    
    // 赋值不同类型
    v = 42;
    std::cout << "Holds int: " << std::get<int>(v) << std::endl;
    
    v = 3.14;
    std::cout << "Holds double: " << std::get<double>(v) << std::endl;
    
    v = "hello";
    std::cout << "Holds string: " << std::get<std::string>(v) << std::endl;
    
    // 检查当前持有的类型索引
    std::cout << "Current index: " << v.index() << std::endl;  // 输出2
    
    // 使用holds_alternative检查类型
    if (std::holds_alternative<std::string>(v)) {
        std::cout << "Currently holds a string" << std::endl;
    }
    
    // 安全访问(推荐)
    try {
        std::cout << std::get<double>(v) << std::endl;  // 抛出异常
    } catch (const std::bad_variant_access& e) {
        std::cout << "Bad access: " << e.what() << std::endl;
    }
}

// 示例2:visitor模式(使用std::visit)
// 定义visitor(函数对象)
struct PrintVisitor {
    void operator()(int i) const {
        std::cout << "int: " << i << std::endl;
    }
    void operator()(double d) const {
        std::cout << "double: " << d << std::endl;
    }
    void operator()(const std::string& s) const {
        std::cout << "string: " << s << std::endl;
    }
};

// 使用lambda作为visitor
void example_visitor() {
    std::variant<int, double, std::string> v = "test";
    
    // 使用函数对象
    std::visit(PrintVisitor{}, v);
    
    // 使用lambda(C++17支持)
    auto lambda_visitor = [](auto&& arg) {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<T, int>) {
            std::cout << "Got int: " << arg << std::endl;
        } else if constexpr (std::is_same_v<T, double>) {
            std::cout << "Got double: " << arg << std::endl;
        } else if constexpr (std::is_same_v<T, std::string>) {
            std::cout << "Got string: " << arg << std::endl;
        }
    };
    
    v = 10;
    std::visit(lambda_visitor, v);
    
    v = 2.5;
    std::visit(lambda_visitor, v);
}

// 示例3:错误处理
std::variant<std::string, std::runtime_error> parse_input(const std::string& input) {
    if (input.empty()) {
        return std::runtime_error("Empty input");
    }
    if (input[0] == 'E') {
        return std::runtime_error("Input starts with E");
    }
    return "Processed: " + input;
}

void example_error_handling() {
    auto result = parse_input("");
    
    std::visit([](auto&& arg) {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<T, std::string>) {
            std::cout << "Success: " << arg << std::endl;
        } else if constexpr (std::is_same_v<T, std::runtime_error>) {
            std::cout << "Error: " << arg.what() << std::endl;
        }
    }, result);
}

// 示例4:递归variant(树结构)
struct TreeNode;
using TreeNodeVariant = std::variant<int, std::unique_ptr<TreeNode>>;

struct TreeNode {
    TreeNodeVariant left;
    TreeNodeVariant right;
    int value;
    
    TreeNode(int val, TreeNodeVariant l, TreeNodeVariant r)
        : value(val), left(std::move(l)), right(std::move(r)) {}
};

int calculate_tree(const TreeNodeVariant& node) {
    return std::visit([](auto&& arg) -> int {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<T, int>) {
            return arg;  // 叶子节点
        } else {
            // 内部节点
            auto& tree = *arg;
            int left_val = calculate_tree(tree.left);
            int right_val = calculate_tree(tree.right);
            return tree.value + left_val + right_val;
        }
    }, node);
}

// 示例5:状态机
class Connection {
public:
    enum State { Disconnected, Connecting, Connected, Error };
    
private:
    std::variant<
        struct DisconnectedState,
        struct ConnectingState,
        struct ConnectedState,
        struct ErrorState
    > state;
    
public:
    Connection() : state(DisconnectedState{}) {}
    
    void connect() {
        state = std::visit([](auto&& s) -> decltype(state) {
            using T = std::decay_t<decltype(s)>;
            if constexpr (std::is_same_v<T, DisconnectedState>) {
                std::cout << "Starting connection..." << std::endl;
                return ConnectingState{};
            } else if constexpr (std::is_same_v<T, ConnectingState>) {
                std::cout << "Already connecting..." << std::endl;
                return s;
            } else if constexpr (std::is_same_v<T, ConnectedState>) {
                std::cout << "Already connected" << std::endl;
                return s;
            } else {
                std::cout << "Cannot connect from error state" << std::endl;
                return s;
            }
        }, state);
    }
    
    void print_state() const {
        std::cout << "Current state index: " << state.index() << std::endl;
    }
};

// 示例6:解析多种类型数据
struct JSONNull {};
using JSONValue = std::variant<
    JSONNull,
    bool,
    int,
    double,
    std::string,
    std::vector<JSONValue>,
    std::map<std::string, JSONValue>
>;

void print_json(const JSONValue& value, int indent = 0) {
    std::string spaces(indent * 2, ' ');
    
    std::visit([&](auto&& arg) {
        using T = std::decay_t<decltype(arg)>;
        
        if constexpr (std::is_same_v<T, JSONNull>) {
            std::cout << spaces << "null";
        } else if constexpr (std::is_same_v<T, bool>) {
            std::cout << spaces << (arg ? "true" : "false");
        } else if constexpr (std::is_same_v<T, int>) {
            std::cout << spaces << arg;
        } else if constexpr (std::is_same_v<T, double>) {
            std::cout << spaces << arg;
        } else if constexpr (std::is_same_v<T, std::string>) {
            std::cout << spaces << "\"" << arg << "\"";
        } else if constexpr (std::is_same_v<T, std::vector<JSONValue>>) {
            std::cout << spaces << "[\n";
            for (const auto& elem : arg) {
                print_json(elem, indent + 1);
                std::cout << ",\n";
            }
            std::cout << spaces << "]";
        } else if constexpr (std::is_same_v<T, std::map<std::string, JSONValue>>) {
            std::cout << spaces << "{\n";
            for (const auto& [key, val] : arg) {
                std::cout << spaces << "  \"" << key << "\": ";
                print_json(val, 0);
                std::cout << ",\n";
            }
            std::cout << spaces << "}";
        }
    }, value);
}

// 示例7:类型安全的回调
using Callback = std::variant<
    std::function<void(int)>,
    std::function<void(std::string)>,
    std::function<void(double)>
>;

class EventDispatcher {
    std::vector<Callback> callbacks;
    
public:
    void add_callback(Callback cb) {
        callbacks.push_back(std::move(cb));
    }
    
    void dispatch(int value) {
        for (auto& cb : callbacks) {
            if (auto* func = std::get_if<std::function<void(int)>>(&cb)) {
                (*func)(value);
            }
        }
    }
    
    void dispatch(const std::string& value) {
        for (auto& cb : callbacks) {
            if (auto* func = std::get_if<std::function<void(std::string)>>(&cb)) {
                (*func)(value);
            }
        }
    }
};

// 示例8:get_if安全访问
void example_get_if() {
    std::variant<int, std::string> v = "hello";
    
    // 使用get_if(不抛出异常)
    if (auto* str_ptr = std::get_if<std::string>(&v)) {
        std::cout << "String value: " << *str_ptr << std::endl;
    }
    
    if (auto* int_ptr = std::get_if<int>(&v)) {
        std::cout << "Int value: " << *int_ptr << std::endl;
    } else {
        std::cout << "Not holding int" << std::endl;
    }
}

// 示例9:monadic操作(C++23引入,这里模拟)
template<typename... Ts>
struct VariantWrapper {
    std::variant<Ts...> var;
    
    template<typename Func>
    auto and_then(Func&& func) {
        return std::visit([&func](auto&& arg) {
            return func(std::forward<decltype(arg)>(arg));
        }, var);
    }
};

// 示例10:性能考虑
void example_performance() {
    // variant使用栈内存,大小是最大类型+类型索引
    std::variant<int, double, std::array<char, 100>> v;
    std::cout << "Size of variant: " << sizeof(v) << " bytes" << std::endl;
    
    // 与union比较
    union TraditionalUnion {
        int i;
        double d;
        char str[100];
    };
    std::cout << "Size of union: " << sizeof(TraditionalUnion) << " bytes" << std::endl;
}

int main() {
    example_basic();
    example_visitor();
    example_error_handling();
    example_get_if();
    example_performance();
    
    // 状态机示例
    Connection conn;
    conn.connect();
    conn.print_state();
    
    // JSON示例
    JSONValue json = std::map<std::string, JSONValue>{
        {"name", "John"},
        {"age", 30},
        {"scores", std::vector<JSONValue>{85, 90, 78}},
        {"active", true}
    };
    
    std::cout << "\nJSON output:\n";
    print_json(json);
    std::cout << std::endl;
    
    return 0;
}

std::string_view 详细用法

(零拷贝)string_view(零拷贝)

复制代码
void print(std::string_view sv) {
    std::cout << sv;
}

print("hello");
print(std::string("world"));

📌 工程价值

  • 传参无拷贝
  • 性能友好(日志、解析)

具体使用,如下:

c 复制代码
#include <iostream>
#include <string_view>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring>

// 定义:字符串的非拥有视图,只读访问,不管理内存

// 示例1:基本创建和使用
void example_basic() {
    // 从C风格字符串创建
    const char* cstr = "Hello, World!";
    std::string_view sv1(cstr);
    std::cout << "sv1: " << sv1 << ", size: " << sv1.size() << std::endl;
    
    // 从std::string创建
    std::string str = "Hello from std::string";
    std::string_view sv2(str);
    std::cout << "sv2: " << sv2 << std::endl;
    
    // 从字符串字面量创建
    std::string_view sv3 = "String literal";
    std::cout << "sv3: " << sv3 << std::endl;
    
    // 从子字符串创建
    std::string_view sv4 = sv1.substr(0, 5);  // "Hello"
    std::cout << "sv4 (substr): " << sv4 << std::endl;
    
    // 从指针和长度创建
    const char* data = "Raw data";
    std::string_view sv5(data, 3);  // "Raw"
    std::cout << "sv5 (pointer+len): " << sv5 << std::endl;
    
    // 从数组创建
    char arr[] = {'H', 'i', '!', '\0'};
    std::string_view sv6(arr);
    std::cout << "sv6 (array): " << sv6 << std::endl;
}

// 示例2:作为函数参数(高效,无拷贝)
void print_string(std::string_view sv) {
    std::cout << "Received: " << sv 
              << ", Length: " << sv.length() 
              << ", Data: " << sv.data() << std::endl;
}

std::string_view find_word(std::string_view text, std::string_view word) {
    size_t pos = text.find(word);
    if (pos != std::string_view::npos) {
        return text.substr(pos, word.length());
    }
    return {};  // 空string_view
}

void example_function_parameters() {
    // 可以接受各种字符串类型,无拷贝
    print_string("C string");
    
    std::string str = "std::string";
    print_string(str);
    
    std::string_view sv = "string_view";
    print_string(sv);
    
    // 查找示例
    std::string_view text = "The quick brown fox jumps over the lazy dog";
    std::string_view found = find_word(text, "fox");
    if (!found.empty()) {
        std::cout << "Found: " << found << std::endl;
    }
}

// 示例3:字符串操作(只读)
void example_string_operations() {
    std::string_view sv = "Hello, World! Programming is fun!";
    
    // 查找
    size_t pos = sv.find("World");
    if (pos != std::string_view::npos) {
        std::cout << "'World' found at position: " << pos << std::endl;
    }
    
    // 比较
    std::string_view sv2 = "Hello";
    if (sv.compare(0, 5, sv2) == 0) {
        std::cout << "Starts with 'Hello'" << std::endl;
    }
    
    // 移除前缀/后缀
    std::string_view sv3 = sv;
    sv3.remove_prefix(7);  // 移除"Hello, "
    std::cout << "After remove_prefix: " << sv3 << std::endl;
    
    sv3.remove_suffix(19);  // 移除"! Programming is fun!"
    std::cout << "After remove_suffix: " << sv3 << std::endl;
    
    // 检查是否以特定字符串开头/结尾
    if (sv.starts_with("Hello")) {
        std::cout << "Starts with Hello" << std::endl;
    }
    
    if (sv.ends_with("fun!")) {
        std::cout << "Ends with fun!" << std::endl;
    }
}

// 示例4:与标准算法结合
void example_with_algorithms() {
    std::vector<std::string_view> words = {
        "apple", "banana", "cherry", "date", "elderberry"
    };
    
    // 查找包含特定字符的单词
    auto it = std::find_if(words.begin(), words.end(), 
        [](std::string_view sv) {
            return sv.find('a') != std::string_view::npos;
        });
    
    if (it != words.end()) {
        std::cout << "First word with 'a': " << *it << std::endl;
    }
    
    // 排序string_view(按视图排序,不修改原字符串)
    std::sort(words.begin(), words.end());
    std::cout << "Sorted words: ";
    for (const auto& w : words) {
        std::cout << w << " ";
    }
    std::cout << std::endl;
    
    // 使用string_view作为map的key(需要自定义比较器或C++20)
    struct StringViewCompare {
        bool operator()(std::string_view a, std::string_view b) const {
            return a < b;
        }
    };
    
    std::map<std::string_view, int, StringViewCompare> word_count;
    word_count["apple"] = 3;
    word_count["banana"] = 2;
}

// 示例5:性能优势演示
#include <chrono>

void process_string(const std::string& str) {
    // 有拷贝
    volatile size_t len = str.length();  // 防止优化
    (void)len;
}

void process_string_view(std::string_view sv) {
    // 无拷贝
    volatile size_t len = sv.length();
    (void)len;
}

void example_performance() {
    std::string long_string(10000, 'x');  // 创建长字符串
    
    auto start1 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 10000; ++i) {
        process_string(long_string);  // 每次都有拷贝
    }
    auto end1 = std::chrono::high_resolution_clock::now();
    
    auto start2 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 10000; ++i) {
        process_string_view(long_string);  // 无拷贝
    }
    auto end2 = std::chrono::high_resolution_clock::now();
    
    auto time1 = std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1);
    auto time2 = std::chrono::duration_cast<std::chrono::microseconds>(end2 - start2);
    
    std::cout << "std::string time: " << time1.count() << "μs" << std::endl;
    std::cout << "std::string_view time: " << time2.count() << "μs" << std::endl;
    std::cout << "Speedup: " << static_cast<double>(time1.count()) / time2.count() 
              << "x" << std::endl;
}

// 示例6:解析和处理
std::vector<std::string_view> split_string(std::string_view str, 
                                          std::string_view delimiters) {
    std::vector<std::string_view> tokens;
    size_t start = 0;
    size_t end = 0;
    
    while ((end = str.find_first_of(delimiters, start)) != std::string_view::npos) {
        if (end != start) {
            tokens.push_back(str.substr(start, end - start));
        }
        start = end + 1;
    }
    
    if (start < str.length()) {
        tokens.push_back(str.substr(start));
    }
    
    return tokens;
}

void example_parsing() {
    std::string_view csv_line = "apple,banana,cherry,date,elderberry";
    auto fruits = split_string(csv_line, ",");
    
    std::cout << "Parsed fruits:" << std::endl;
    for (const auto& fruit : fruits) {
        std::cout << "  - " << fruit << std::endl;
    }
    
    // 解析配置行
    std::string_view config_line = "timeout = 30";
    size_t eq_pos = config_line.find('=');
    if (eq_pos != std::string_view::npos) {
        std::string_view key = config_line.substr(0, eq_pos);
        std::string_view value = config_line.substr(eq_pos + 1);
        
        // 去除空格
        key.remove_prefix(std::min(key.find_first_not_of(" "), key.size()));
        key.remove_suffix(key.size() - key.find_last_not_of(" ") - 1);
        
        value.remove_prefix(std::min(value.find_first_not_of(" "), value.size()));
        value.remove_suffix(value.size() - value.find_last_not_of(" ") - 1);
        
        std::cout << "Key: '" << key << "', Value: '" << value << "'" << std::endl;
    }
}

// 示例7:注意事项和陷阱
void example_pitfalls() {
    // 陷阱1:悬挂引用
    std::string_view dangerous;
    {
        std::string temp = "temporary string";
        dangerous = temp;  // string_view指向临时字符串
    }  // temp被销毁
    // 危险!dangerous现在指向已释放的内存
    // std::cout << dangerous << std::endl;  // 未定义行为!
    
    // 正确做法:确保原字符串生命周期足够长
    std::string permanent = "permanent string";
    std::string_view safe = permanent;  // 安全
    
    // 陷阱2:不以null结尾
    char buffer[] = {'H', 'e', 'l', 'l', 'o'};  // 没有null终止符
    std::string_view sv(buffer, 5);
    // sv.data()不能保证null终止!
    
    // 如果需要C风格字符串,需要确保有终止符
    std::string_view sv2 = "Hello";
    if (sv2.data()[sv2.size()] == '\0') {
        std::cout << "Properly null-terminated" << std::endl;
    }
    
    // 陷阱3:修改原字符串
    char mutable_buffer[] = "Hello";
    std::string_view sv3(mutable_buffer);
    std::cout << "Before: " << sv3 << std::endl;
    
    mutable_buffer[0] = 'J';
    std::cout << "After: " << sv3 << std::endl;  // 变为"Jello"
}

// 示例8:字符串字面量操作符(C++14引入,这里展示与string_view结合)
constexpr std::string_view operator"" _sv(const char* str, size_t len) {
    return std::string_view(str, len);
}

void example_user_literal() {
    auto sv = "Hello World"_sv;
    static_assert(std::is_same_v<decltype(sv), std::string_view>);
    std::cout << "Using literal: " << sv << ", size: " << sv.size() << std::endl;
}

// 示例9:constexpr string_view(编译期字符串处理)
constexpr std::string_view compile_time_str = "Compile time string";

constexpr bool starts_with_compile(std::string_view sv, std::string_view prefix) {
    return sv.size() >= prefix.size() && 
           sv.substr(0, prefix.size()) == prefix;
}

void example_constexpr() {
    static_assert(compile_time_str.size() == 19);
    static_assert(starts_with_compile(compile_time_str, "Compile"));
    
    constexpr std::string_view local_constexpr = "Local constexpr";
    static_assert(local_constexpr.find("const") != std::string_view::npos);
}

// 示例10:与其它类型互操作
class StringViewWrapper {
    std::string_view view;
    
public:
    // 从各种字符串类型构造
    StringViewWrapper(const char* str) : view(str) {}
    StringViewWrapper(const std::string& str) : view(str) {}
    StringViewWrapper(std::string_view sv) : view(sv) {}
    
    // 转换为std::string(如果需要所有权)
    std::string to_string() const {
        return std::string(view);
    }
    
    // 各种操作
    bool contains(std::string_view substr) const {
        return view.find(substr) != std::string_view::npos;
    }
    
    std::string_view substr(size_t pos, size_t count = std::string_view::npos) const {
        return view.substr(pos, count);
    }
    
    friend std::ostream& operator<<(std::ostream& os, const StringViewWrapper& wrapper) {
        return os << wrapper.view;
    }
};

int main() {
    example_basic();
    example_function_parameters();
    example_string_operations();
    example_with_algorithms();
    example_parsing();
    example_pitfalls();
    example_user_literal();
    example_constexpr();
    
    // 性能测试
    example_performance();
    
    // 包装器示例
    StringViewWrapper wrapper1("C string");
    StringViewWrapper wrapper2(std::string("std::string"));
    StringViewWrapper wrapper3("string_view"sv);
    
    std::cout << "Wrapper1: " << wrapper1 << std::endl;
    std::cout << "Contains 'str': " << wrapper1.contains("str") << std::endl;
    
    return 0;
}

std::filesystem

std::filesystem ⭐⭐⭐⭐⭐

复制代码
#include <filesystem>
namespace fs = std::filesystem;

for (auto& p : fs::directory_iterator("data")) {
    std::cout << p.path() << std::endl;
}

📌 工程价值(你做工程必用)

  • 文件遍历、路径拼接
  • 可逐步替代 Qt 的 QFileInfo(或混用)

C++20 新特性

可以把 C++20 理解为:模板更像人话 + 算法更像流水线 + 异步更像同步


一、Concepts(模板约束)

是什么

给模板加"类型条件",让错误在接口处就暴露。

以前(C++17)

cpp 复制代码
template<typename T>
T add(T a, T b) {
    return a + b; // 不满足会报一堆天书
}

C++20

cpp 复制代码
#include <concepts>

template<std::integral T>
T add(T a, T b) {
    return a + b;
}

add(1, 2);      // ✅
add(1.2, 2.3);  // ❌ 编译期直接拒绝

工程价值

  • 模板报错瞬间"像人话"
  • 写库、写算法非常爽

二、Ranges(算法 & 容器革命)

是什么

STL 算法的"组合版 + 懒执行"

示例

cpp 复制代码
#include <ranges>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1,2,3,4,5,6};

    auto even = v 
        | std::views::filter([](int x) { return x % 2 == 0; })
        | std::views::transform([](int x) { return x * 10; });

    for (int x : even) {
        std::cout << x << " ";
    }
}

 // Ranges方式:惰性求值,无中间存储
    auto result = numbers 
        | rv::filter([](int n) { return n % 2 == 0; })  // 过滤偶数
        | rv::transform([](int n) { return n * n; })    // 平方
        | rv::take(3);                                  // 取前3个

工程价值

  • 数据处理"管道化"
  • 非常适合 UI / 数据流 / 解析逻辑

三、Coroutine(协程)(进阶)

是什么

把异步写成同步代码

极简示例(概念理解)

cpp 复制代码
#include <coroutine>

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 foo() {
    co_return;
}

工程价值

  • 网络
  • IO
  • 后台任务

⚠️ Qt 目前更多是 concept + future + thread,协程别急


四、std::span(安全的数组视图)

是什么

非拥有的连续内存视图(安全版 T* + size

示例

cpp 复制代码
#include <span>
#include <vector>
#include <iostream>

void process(std::span<int> data) {
    for (int x : data) {
        std::cout << x << " ";
    }
}

int main() {
    std::vector<int> v = {1,2,3};
    process(v);   // 不拷贝
}

工程价值

  • 算法函数参数首选
  • 替代裸指针 + size

五、std::format(现代格式化)⭐⭐⭐⭐⭐

是什么

C++ 原生 fmt,干掉 printf / ostringstream

示例

cpp 复制代码
#include <format>
#include <iostream>

int main() {
    int id = 10;
    double value = 3.14;

    std::cout << std::format("id={}, value={:.2f}", id, value);
}

工程价值

  • 日志系统
  • UI 文案
  • 强类型、可读性高

六、std::ranges::sort 等算法升级

cpp 复制代码
#include <ranges>
#include <vector>

std::vector<int> v = {4,1,3,2};

std::ranges::sort(v);

📌 不再需要:

cpp 复制代码
std::sort(v.begin(), v.end());

七、三路比较 <=>(太空船运算符)

是什么

自动生成所有比较运算符

示例

cpp 复制代码
#include <compare>

struct Point {
    int x;
    int y;

    auto operator<=>(const Point&) const = default;
};

你立刻拥有:

  • <
  • >
  • ==
  • !=

工程价值

  • 数据结构
  • map / set key

八、consteval / constexpr 升级

是什么

更强的编译期计算

cpp 复制代码
consteval int square(int x) {
    return x * x;
}

int main() {
    int a = square(5); // 必须编译期
}

九、std::jthread(自动 join 的线程)

是什么

RAII 线程,析构自动 join

示例

cpp 复制代码
#include <thread>
#include <iostream>

void work() {
    std::cout << "working\n";
}

int main() {
    std::jthread t(work);
} // 自动 join

工程价值

  • 防止线程泄漏
  • 比 std::thread 安全

十、std::stop_token(线程取消)

cpp 复制代码
#include <thread>
#include <iostream>

void work(std::stop_token st) {
    while (!st.stop_requested()) {
        // do work
    }
}

int main() {
    std::jthread t(work);
    t.request_stop();
}

十一、[[...]]

cpp 复制代码
if (error) [[unlikely]] {
    return;
}

📌 性能提示,非保证

好,这个点问得非常专业 👍

你说的 [[...]] 不是"一个特性",而是 C++11 引入、在 C++17 / C++20 里逐步增强的一整套:

👉 标准属性(attributes)机制

我给你来一版从底层认知 → 常用属性 → 工程实战 → 易踩坑的完整讲解。


一、[[...]] 到底是什么?

定义(人话版)

[[...]]给编译器看的"元信息"

不改变语义,只影响:

  • 编译器诊断(warning / error)
  • 优化策略
  • 代码意图表达

📌 核心原则:

属性不会改变程序逻辑,只是"提示 / 约束 / 标注"


二、为什么 C++ 要引入 [[...]]

在它之前(C 风格)

cpp 复制代码
__attribute__((unused))
__declspec(noreturn)

❌ 问题:

  • 编译器相关
  • 不可移植

C++ 的目标

cpp 复制代码
[[nodiscard]]
[[maybe_unused]]
[[likely]]

✔ 统一

✔ 可移植

✔ 可组合

三、最常用、你必须会的标准属性 ⭐⭐⭐⭐⭐

1️⃣ [[nodiscard]](最重要)

是什么

返回值不能被忽略

示例

cpp 复制代码
[[nodiscard]]
int calc() {
    return 42;
}

int main() {
    calc();      // ⚠️ 编译警告
    int x = calc(); // ✅
}

工程场景

  • 错误码
  • 资源句柄
  • std::optional / expected

📌 C++17 起支持


2️⃣ [[maybe_unused]]

是什么

消除"未使用变量 / 参数"的警告

示例

cpp 复制代码
void foo([[maybe_unused]] int debugFlag) {
    // debugFlag 可能在某些宏下使用
}

工程场景

  • 跨平台
  • Debug / Release 不同逻辑

3️⃣ [[likely]] / [[unlikely]](C++20)

是什么

告诉编译器:这个分支更可能 / 不太可能发生

示例

cpp 复制代码
if (value < 0) [[unlikely]] {
    return;
}

注意

  • 提示,不是命令
  • 编译器可忽略

📌 适合:

  • 错误路径
  • 兜底分支

4️⃣ [[fallthrough]](switch 专用)

是什么

显式允许 case 穿透

示例

cpp 复制代码
switch (x) {
case 1:
    doA();
    [[fallthrough]];
case 2:
    doB();
    break;
}

📌 防止误写漏 break


5️⃣ [[deprecated]]

是什么

标记"过时接口"

示例

cpp 复制代码
[[deprecated("Use newFunc instead")]]
void oldFunc() {}

调用时编译器会警告。

📌 工程价值:

  • 平滑重构
  • API 演进

四、属性可以用在哪里?

属性不是随便放的,它有作用域

cpp 复制代码
[[nodiscard]] int foo();        // 函数
[[deprecated]] struct A {};     // 类型
void bar([[maybe_unused]] int); // 参数
[[likely]] if (...) {}          // 语句

五、属性 ≠ 宏(这是重点)

对比

属性
作用于语法层 文本替换
有作用域 无作用域
可被工具识别 不易分析
标准化 编译器私有

👉 能用 [[...]],别用宏


六、编译器相关属性(了解即可)

cpp 复制代码
[[gnu::unused]]
[[msvc::noinline]]

示例

cpp 复制代码
[[gnu::unused]] int x;

📌 命名空间隔离,不冲突


七、你工程里可以"立刻用起来"的组合

1️⃣ 返回值强制检查

cpp 复制代码
[[nodiscard]]
bool loadConfig();

2️⃣ 错误路径优化

cpp 复制代码
if (!ptr) [[unlikely]] {
    return;
}

3️⃣ 安全 switch

cpp 复制代码
switch (state) {
case A:
    ...
    [[fallthrough]];
case B:
    ...
}

4️⃣ 渐进式重构

cpp 复制代码
[[deprecated("Use NewApi")]]
void OldApi(); // 这段话可能过时,不去使用

八、容易踩的坑(一定要知道)

❌ 属性不会改变逻辑

cpp 复制代码
[[nodiscard]] int x = 10; // ❌ 没意义

❌ likely 不是性能魔法

cpp 复制代码
if (hotPath) [[likely]] { ... }

👉 编译器可能忽略

❌ 属性不是注释

cpp 复制代码
[[deprecated]] // 不等于注释

九、总结一句"工程级理解"

[[...]]写给"编译器 + 未来维护者"的注释

不是给机器跑逻辑的


十二、std::remove_cvref_t

cpp 复制代码
using T = std::remove_cvref_t<decltype(arg)>;

👉 替代 std::decay_t 的常见用途


十三、constexpr 容器(重要但低调)

cpp 复制代码
constexpr std::vector<int> make() {
    return {1,2,3};
}


相关推荐
行稳方能走远2 小时前
Android C++ 学习笔记 2
android·c++
浅川.252 小时前
STL专项:deque 双端队列
开发语言·c++·stl·deque
mmz12072 小时前
差分数组(二维)(c++)
c++·算法
闻缺陷则喜何志丹2 小时前
【计算几何 化环为链】P14165 [ICPC 2022 Nanjing R] 清空水箱|普及+
c++·数学·算法·计算几何·洛谷·化环为链
爱吃生蚝的于勒2 小时前
【Linux】深入理解软硬链接
linux·运维·服务器·c语言·数据结构·c++·算法
老王熬夜敲代码3 小时前
C++模版元编程1
数据结构·c++·笔记
小李小李快乐不已3 小时前
动态规划理论基础
数据结构·c++·算法·leetcode·动态规划
leaves falling3 小时前
c语言数组-求10 个整数中最大值
c语言·c++·算法