常见的可以提升编码效率的 modern C++ 语法糖【1】

文章目录

std::optional

std::optional 是 C++17 中引入的一个模板类,它可以表示一个可能不存在的值。std::optional 的使用方法非常简单,它可以用于任何类型,包括内置类型、自定义类型和 STL 容器等。

以下是 std::optional 的一些常用操作:

  1. std::optional<T>:表示一个可能不存在的类型为 T 的值。
  2. std::nullopt:表示一个不存在的值。
  3. std::optional<T>::value:获取 std::optional<T> 中的值,如果不存在则抛出异常。
  4. std::optional<T>::value_or:获取 std::optional<T> 中的值,如果不存在则返回指定的默认值。
  5. std::optional<T>::has_value:判断 std::optional<T> 是否存在值。
  6. std::optional<T>::reset:将 std::optional<T> 的值重置为不存在。

以下是一个使用 std::optional 的示例代码:

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

std::optional<int> divide(int a, int b) {
    if (b == 0) {
        return std::nullopt;
    } else {
        return a / b;
    }
}

int main() {
    auto result = divide(10, 2);

    if (result.has_value()) {
        std::cout << "The result is " << result.value() << std::endl;
    } else {
        std::cout << "Cannot divide by zero" << std::endl;
    }

    auto result2 = divide(10, 0);

    if (result2.has_value()) {
        std::cout << "The result is " << result2.value() << std::endl;
    } else {
        std::cout << "Cannot divide by zero" << std::endl;
    }

    return 0;
}

std::string_view的使用

std::string_view是C++17标准中引入的一种轻量级字符串视图类型,可以用于表示字符串的一部分或整个字符串,而不需要进行内存分配或拷贝。下面是一个std::string_view的使用示例:

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

int main() {
    std::string str = "Hello, world!";
    std::string_view view1(str); // 从std::string构造std::string_view
    std::string_view view2(str.data() + 7, 5); // 从字符指针和长度构造std::string_view
    std::cout << view1 << std::endl; // 输出整个字符串
    std::cout << view2 << std::endl; // 输出"world"
    return 0;
}

在上面的示例中,我们首先定义了一个std::string类型的字符串str,然后使用std::string_view类型的view1和view2表示字符串的一部分或整个字符串。其中,view1使用std::string类型的构造函数进行构造,而view2使用字符指针和长度进行构造。最后,我们使用std::cout输出了view1和view2表示的字符串。

需要注意的是,std::string_view类型只是字符串的一个视图,不拥有字符串的内存,因此需要确保原始字符串的生命周期大于或等于std::string_view类型的生命周期。同时,std::string_view类型也不支持修改字符串,只能用于读取字符串的内容。

std::variant使用

std::variant 是 C++17 中引入的一个模板类,它可以表示多个可能的类型。std::variant 的使用方法非常简单,它可以用于任何类型,包括内置类型、自定义类型和 STL 容器等。

以下是 std::variant 的一些常用操作:

  1. std::variant<Ts...>:表示多个可能的类型 Ts...
  2. std::get<N>(std::variant<Ts...>&):获取 std::variant<Ts...> 中的第 N 个类型的值,如果类型不匹配则抛出异常。
  3. std::get_if<N>(std::variant<Ts...>*):获取 std::variant<Ts...> 中的第 N 个类型的指针,如果类型不匹配则返回 nullptr
  4. std::variant<Ts...>::index():获取 std::variant<Ts...> 中当前值的类型索引。
  5. std::variant<Ts...>::valueless_by_exception():判断 std::variant<Ts...> 是否存在值。

以下是一个使用 std::variant 的示例代码:

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

int main() {
    std::variant<int, double, std::string> v;

    v = 10;
    std::cout << std::get<int>(v) << std::endl;

    v = 3.14;
    std::cout << std::get<double>(v) << std::endl;

    v = "hello";
    std::cout << std::get<std::string>(v) << std::endl;

    if (auto p = std::get_if<int>(&v)) {
        std::cout << "The value is " << *p << std::endl;
    } else if (auto p = std::get_if<double>(&v)) {
        std::cout << "The value is " << *p << std::endl;
    } else if (auto p = std::get_if<std::string>(&v)) {
        std::cout << "The value is " << *p << std::endl;
    }

    return 0;
}

在这个示例代码中,我们定义了一个名为 vstd::variant 对象,它可以存储 intdoublestd::string 三种类型的值。然后,我们分别将 v 赋值为 103.14"hello",并使用 std::get 函数获取 v 中的值。接着,我们使用 std::get_if 函数获取 v 中的值的指针,并根据指针的类型输出不同的信息。

总之,std::variant 是一个非常实用的模板类,它可以帮助我们处理多个可能的类型,避免手动使用枚举或联合体。但是,由于它可能会导致类型不匹配或异常,因此在使用时需要格外小心,避免出现不必要的错误。

std::function 与 std::bind函数

std::functionstd::bind 是 C++11 中引入的两个非常实用的模板类,它们可以帮助我们实现函数对象和函数绑定。下面是一个使用 std::functionstd::bind 的示例代码:

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

void print(int a, int b, int c) {
    std::cout << a << " " << b << " " << c << std::endl;
}

int main() {
    auto f1 = std::bind(print, 1, 2, 3);
    f1();

    auto f2 = std::bind(print, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    f2(4, 5, 6);

    std::function<void(int, int, int)> f3 = std::bind(print, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    f3(7, 8, 9);

    return 0;
}

在这个示例代码中,我们定义了一个名为 print 的函数,它接受三个整数参数,并将它们输出到标准输出流中。然后,我们使用 std::bind 函数创建了两个函数对象 f1f2,它们分别绑定了 print 函数的三个参数。其中,f1 绑定了具体的参数值 123,而 f2 使用了占位符 std::placeholders::_1std::placeholders::_2std::placeholders::_3,表示在调用 f2 时需要传入三个参数。

接着,我们使用 std::function 定义了一个函数对象 f3,它的类型是 void(int, int, int),并将 print 函数绑定到了 f3 上。最后,我们分别调用了 f1f2f3,并传入了不同的参数。

总之,std::functionstd::bind 是 C++11 中非常实用的模板类,它们可以帮助我们实现函数对象和函数绑定,从而实现更加灵活和高效的编程。在实际开发中,我们可以根据需要灵活地使用它们,提高代码的可读性和可维护性。

std::forward使用

std::forward 是 C++11 中的一个模板函数,它的作用是将一个参数以原始的形式转发给另一个函数。std::forward 通常用于实现完美转发,它可以确保参数以原始的形式传递给其他函数,而不会丢失任何信息或进行不必要的拷贝。

std::forward 的作用是根据参数的类型来选择将其转发为左值引用或右值引用。如果参数是一个左值,那么 std::forward 将返回一个左值引用类型的值,即 T&。如果参数是一个右值,那么 std::forward 将返回一个右值引用类型的值,即 T&&

std::forward 的实现依赖于引用折叠的规则。当我们使用 std::forward 时,我们必须将参数的类型指定为模板参数,以便编译器可以根据参数的类型来推断出正确的引用类型。例如,如果我们要将一个参数 arg 转发给另一个函数,我们可以使用以下代码:

cpp 复制代码
template<typename T>
void forwarder(T&& arg) {
    other_function(std::forward<T>(arg));
}

在这个示例代码中,我们使用了 T&& 作为参数类型,这意味着它可以接受任何类型的参数,包括左值和右值。然后,我们使用 std::forward 函数将参数 arg 以原始的形式转发给另一个函数 other_function

相关推荐
LUCIAZZZ34 分钟前
手写单例模式
java·开发语言·spring boot·单例模式
程序员东min2 小时前
C++:抽象类习题
开发语言·c++
二十雨辰3 小时前
[Java基础]开发工具Idea
java·intellij-idea
摸鱼仙人~3 小时前
Git如何避免推送.idea文件夹
java·git·intellij-idea
zzb15803 小时前
项目集成Spring Security认证部分
java·后端·spring
Victoria.a3 小时前
string类详解
数据结构·c++
程序猿小D4 小时前
第三百五十八节 JavaFX教程 - JavaFX滑块
java·前端·数据库
转调6 小时前
第九章:内存池的调整与测试
c++·内存池
行路见知6 小时前
1.5 Go切片使用
开发语言·golang
XY_墨莲伊7 小时前
【算法设计与分析】实验5:贪心算法—装载及背包问题
c语言·数据结构·c++·算法·贪心算法·排序算法