C++11学习笔记(4)——通用工具(下)

news2024/12/23 10:27:03

太长了,分两篇写吧
书接上回

4.数值极值

std::numeric_limits 是 C++ 标准库中定义的一个模板类,位于 头文件中。它提供了关于各种数值类型的属性和极值的信息。这些信息可以帮助我们在程序中进行数值处理时,了解特定类型的数值范围、精度以及其他一些与数值相关的特性。

最小精度

类型最小长度
char1 byte
short int2 bytes
int2 bytes
long int4 bytes
long long int8 bytes
float4 bytes
double8 bytes
long double8 bytes

通用numeric_limits

template<typename T>
class numeric_limits {
public:
    static constexpr bool is_specialized = false;

    static constexpr T min() noexcept {
        return T();
    }

    static constexpr T max() noexcept {
        return T();
    }

    // 其他成员函数和常量...
};

通用模板提供默认极值是指当使用 std::numeric_limits 的通用模板时,如果没有对特定类型进行特化,它将提供一组默认的极值。

对于基本数据类型(如整数、浮点数等),通用模板会根据类型的特性提供合适的默认极值。例如,对于有符号整数类型 int,std::numeric_limits::min() 返回的是该类型的最小值,std::numeric_limits::max() 返回的是该类型的最大值。

对于浮点数类型,std::numeric_limits::min() 返回的是该类型的最小正值,std::numeric_limits::max() 返回的是该类型的最大有限值。

通用模板还提供其他一些默认的极值信息,如精度、舍入误差等。这些默认的极值是基于类型的一般特性和标准规范而定义的。

#include <iostream>
#include <limits>

int main() {
    std::cout << "int 类型的最小值:" << std::numeric_limits<int>::min() << std::endl;
    std::cout << "int 类型的最大值:" << std::numeric_limits<int>::max() << std::endl;
    std::cout << "float 类型的最小精度:" << std::numeric_limits<float>::epsilon() << std::endl;
    std::cout << "double 类型的正无穷大:" << std::numeric_limits<double>::infinity() << std::endl;
    std::cout << "double 类型的静默非数值(NaN):" << std::numeric_limits<double>::quiet_NaN() << std::endl;
    std::cout << "double 类型的位数:" << std::numeric_limits<double>::digits << std::endl;

    return 0;
}

特化numeric_limits

对于某些特定的数据类型,如用户自定义的类类型或特殊的数值类型,这些默认值可能不适用,因为这些类型可能具有不同的数值范围或特殊行为。为了满足这些特殊情况,可以对 std::numeric_limits 进行特化。

特化是通过提供特定类型的模板特化版本来实现的,以覆盖默认的属性和极值。通过特化 std::numeric_limits,我们可以为特定类型提供自定义的极值和属性信息。

以下是一个示例,展示了如何特化 std::numeric_limits 来为自定义类型 MyType 提供自定义的极值和属性信息:

#include <iostream>
#include <limits>

class MyType {
    // 自定义类型的定义和实现
};

namespace std {
    template <>
    class numeric_limits<MyType> {
    public:
    	static constexpr bool is_specialized = true;
        static constexpr MyType min() { return MyType{}; }  // 自定义的最小值
        static constexpr MyType max() { return MyType{}; }  // 自定义的最大值
    };
}

int main() {
    std::cout << "MyType 类型的最小值:" << std::numeric_limits<MyType>::min() << std::endl;
    std::cout << "MyType 类型的最大值:" << std::numeric_limits<MyType>::max() << std::endl;

    return 0;
}

在上面的示例中,我们通过在 std 命名空间下定义一个特化版本的 std::numeric_limits 来为自定义类型 MyType 提供了自定义的最小值和最大值。通过特化,我们可以根据需要为任何类型提供自定义的极值和属性信息。

需要注意的是,特化 std::numeric_limits 是一种高级用法,通常在处理自定义类型或特殊需求时才会使用。对于大多数基本数据类型,通常使用默认的 std::numeric_limits 即可满足需求。

补充

通用性numeric_limits和特化版本都被放在< limite >头文件中,特化版本涵盖所有数值基础类型。
原本的C常量定义于<climits>,<limits.h>,<cfloat>,<float.h>
在这里插入图片描述在这里插入图片描述在这里插入图片描述

5.Type trait

类型特性(Type Traits)是C++中的一组模板类,用于在编译时获取和操作类型信息。它们提供了一种在编译时进行类型检查和操作的方式,使得编译器能够根据类型的属性进行条件编译、类型转换和模板特化等操作。

针对整数类型的弹性重载

假设有一个函数可能传入整数型和浮点型的实参,通常需要写多个重载函数包括short,int,float,double等等类型,不但繁琐而且需要补充新的类型,而Type trait可以简化。

#include <iostream>
#include <type_traits>

// 重载版本1:针对整数类型
template <typename T>
typename std::enable_if<std::is_integral<T>::value>::type
process(T value) {
    std::cout << "整数值:" << value << std::endl;
}

// 重载版本2:针对非整数类型
template <typename T>
typename std::enable_if<!std::is_integral<T>::value>::type
process(T value) {
    std::cout << "非整数值:" << value << std::endl;
}

int main() {
    process(10);        // 调用重载版本1,传入整数类型
    process(3.14);      // 调用重载版本2,传入非整数类型

    return 0;
}

这样只需要两份实现就包含了多种参数类型

处理共通类型

共通类型(Common Type)指的是一组类型中能够进行操作并返回一个一致类型的最低公共类型。在C++中,可以使用 std::common_type 类型特性模板来获取一组类型的最低公共类型。

下面是一个示例代码,演示了如何使用 std::common_type 来处理共通类型:

#include <iostream>
#include <type_traits>

template <typename T1, typename T2>
void process(T1 value1, T2 value2) {
    using CommonType = typename std::common_type<T1, T2>::type;
    CommonType result = value1 + value2;
    std::cout << "结果:" << result << std::endl;
}

int main() {
    process(10, 3.14);      // 传入整数和浮点数
    process(5.5, 2.7);      // 传入两个浮点数
    process(7, 8);          // 传入两个整数

    return 0;
}

在上述示例中,我们定义了一个 process 函数模板,接受两个参数 value1 和 value2,并使用 std::common_type 获取这两个参数的最低公共类型 CommonType。然后,我们使用 CommonType 来声明一个变量 result,对 value1 和 value2 进行加法运算并将结果赋值给 result。最后,我们输出结果到控制台。

在 main 函数中,我们分别调用了 process 函数传入不同类型的参数,包括整数和浮点数。std::common_type 会自动推导出最低公共类型,并将结果进行相应的类型转换和运算。

通过使用 std::common_type,我们可以处理一组具有不同类型的参数,并获取它们的最低公共类型,从而实现对共通类型的处理。这在泛型编程和模板元编程中非常有用,可以处理各种类型组合的操作。

其他操作

针对所有类型

在这里插入图片描述

针对class类

在这里插入图片描述

注意bool和所有character都被视为整数类

检验类型关系

在这里插入图片描述

类型改变

在这里插入图片描述

其他

在这里插入图片描述

reference wrapper

std::reference_wrapper 是 C++ 标准库中的类模板,位于 头文件中。它用于包装引用类型,提供了一种轻量级的引用语义,允许以引用的方式传递和操作对象。

std::reference_wrapper 的主要作用是将引用类型封装成对象,使其具有对象语义。这样可以方便地将引用作为函数参数传递,存储在容器中,或者用于其他需要对象的场合,而不会引入额外的指针语义和内存管理。

使用 std::reference_wrapper 可以实现以下功能:

  • 作为函数参数传递引用:可以将引用作为函数参数传递,而不需要使用指针或拷贝对象。
  • 存储引用类型:可以将引用类型存储在容器中,如 std::vector<std::reference_wrapper>。
  • 在算法中使用引用:可以在标准库的算法中使用引用类型,而不需要使用指针或拷贝对象。

下面是一个示例代码,演示了如何使用

#include <iostream>
#include <functional>

void increment(int& value) {
    ++value;
}

int main() {
    int num = 10;
    std::reference_wrapper<int> ref(num);

    increment(ref);

    std::cout << "num: " << num << std::endl;

    return 0;
}

在上述示例中,我们定义了一个 increment 函数,接受一个引用参数并将其递增。在 main 函数中,我们创建了一个 std::reference_wrapper 对象 ref,将 num 的引用传递给它。然后,我们调用 increment 函数并传递 ref,实际上是传递了 num 的引用。最终,我们输出 num 的值,可以看到它已经被递增了。

通过使用 std::reference_wrapper,我们可以以对象的方式传递和操作引用类型,提供了更方便和灵活的引用语义。它在泛型编程、函数对象、STL 算法等场景中经常使用。

Function Type Wrapper

std::function 是 C++ 标准库中提供的一个类模板,用于封装不同类型的可调用对象,并提供一致的调用接口。

std::function 的类模板定义如下:

template<class R, class... Args>
class function<R(Args...)>;

其中,R 是返回类型,Args… 是参数类型列表。

通过使用 std::function,可以创建一个函数对象,该对象可以包装不同类型的可调用实体,例如函数指针、函数对象、成员函数指针、Lambda 表达式等。

std::function 提供了以下主要功能和用法:

  • 封装可调用对象:使用 std::function 可以将各种可调用对象封装为统一的函数对象,使其具有相同的调用接口。
  • 存储和传递可调用对象:std::function 对象可以像普通对象一样进行复制、存储和传递。这使得它非常适用于将可调用对象作为参数传递给函数、存储在容器中或作为类成员变量。
  • 多态调用:通过 std::function,可以以统一的方式调用不同类型的可调用对象,无需关心其具体类型。这使得代码更加灵活和可扩展。

下面是一个示例,演示了如何使用 std::function:

#include <iostream>
#include <functional>

int add(int a, int b) {
    return a + b;
}

class Foo {
public:
    int multiply(int a, int b) {
        return a * b;
    }
};

int main() {
    std::function<int(int, int)> func;

    func = add;
    int result1 = func(3, 4);
    std::cout << "Result1: " << result1 << std::endl;

    Foo foo;
    func = std::bind(&Foo::multiply, &foo, std::placeholders::_1, std::placeholders::_2);
    int result2 = func(3, 4);
    std::cout << "Result2: " << result2 << std::endl;

    return 0;
}

在上述示例中,我们首先定义了一个 add 函数和一个 Foo 类,其中 Foo 类具有一个成员函数 multiply。然后,我们声明了一个 std::function 对象 func,它的函数类型为 int(int, int)。

我们首先将 add 函数赋值给 func,然后使用 func 调用 add 函数并输出结果。接下来,我们使用 std::bind 将 Foo 类的成员函数 multiply 绑定到 func,并传递一个 Foo 类的对象指针和两个占位符作为参数。最后,我们使用 func 调用 Foo::multiply 并输出结果。


占位符(placeholders)是 C++ 标准库 中的特殊对象,用于占据函数对象的参数位置。在函数对象中,占位符表示该位置的参数将在实际调用时被替换为相应的值。

在 std::bind 的用法中,占位符 std::placeholders::_1、std::placeholders::_2、std::placeholders::_3,以及更多依次递增的占位符 _4、_5 等,用于标识函数对象的参数位置。通过占位符,我们可以在绑定函数时指定参数的位置,而不需要提供实际的参数值。

在示例代码中,我们使用了两个占位符 std::placeholders::_1 和 std::placeholders::_2:

func = std::bind(&Foo::multiply, &foo, std::placeholders::_1, std::placeholders::_2);

在这里,我们将 Foo::multiply 成员函数绑定到 func,并使用两个占位符指定参数的位置。这意味着当我们调用 func 时,参数将被传递到占位符所对应的位置。

在实际调用 func(3, 4) 时,占位符 std::placeholders::_1 对应第一个参数,即 3,占位符 std::placeholders::_2 对应第二个参数,即 4。因此,参数 3 和 4 将被传递给 Foo::multiply 成员函数作为实际的参数。

占位符的使用可以使函数对象更加灵活,尤其在函数对象的绑定和参数位置映射方面。它允许我们推迟参数的传递,并在调用函数对象时动态地提供参数值。

需要注意的是,占位符的个数和位置应与函数对象的参数个数和位置相匹配。否则,将导致参数传递的不正确或编译错误。

在示例中,使用占位符的目的是将绑定的函数对象与 foo 对象和参数位置关联起来。这样,当我们调用绑定的函数对象时,它会在 foo 对象上调用 multiply 函数,并将相应位置的参数传递给该函数。


通过 std::function,我们可以将不同类型的可调用对象封装为一个统一的对象,并以统一的方式进行调用。这提供了更大的灵活性和通用性,使得函数对象的使用更加方便和可扩展。

6.辅助函数

最大最小值

所有minmax()函数和所有带初值列的函数都始于c++11
在这里插入图片描述当我们使用 头文件中的函数时,通常需要指定比较函数(或谓词),以确定元素的顺序或满足其他条件。比较函数是一个可调用对象,接受两个参数,并返回一个布尔值,用于比较两个元素的顺序。

自定义比较

以下是一个使用比较函数进行排序的例子:


#include <algorithm>
#include <vector>
#include <iostream>

bool cmp(int a, int b) {
    // 按照绝对值大小进行比较
    return std::abs(a) < std::abs(b);
}

int main() {
    std::vector<int> nums = {-3, 2, -1, 4, -5};
    std::sort(nums.begin(), nums.end(), cmp);

    for (const auto& num : nums) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在上述示例中,我们定义了一个比较函数 cmp,它按照元素的绝对值大小进行比较。然后,我们使用 std::sort 函数对 nums 容器进行排序,传入 cmp 函数作为比较函数。

排序结果会按照元素的绝对值从小到大进行排序,输出结果为:-1, 2, -3, 4, -5。

通过自定义比较函数,我们可以根据特定的条件对元素进行排序或比较。这在许多算法和操作中都非常有用,例如自定义的排序顺序、按照特定规则筛选元素等等。根据不同的需求,我们可以编写不同的比较函数来满足特定的排序或比较逻辑。

交换两值

std::swap 是 C++ 标准库中的一个通用的交换函数,位于 头文件中。

std::swap 函数有多个重载版本,用于交换不同类型的对象。它的通用模板定义如下:

namespace std {
    template <class T>
    void swap(T& a, T& b);
}

其中,T 是要交换的对象的类型,a 和 b 是要交换的对象的引用。

当调用 std::swap(a, b) 时,根据实际的对象类型,编译器会选择适当的重载版本来执行交换操作。对于内置类型和标准库提供的类型,std::swap 已经有默认的特化版本定义。

此外,对于自定义类型,我们可以通过定义该类型的特化版本或提供自定义的 swap 函数来实现自定义类型的交换操作。例如:

namespace std {
    template <>
    void swap<MyType>(MyType& a, MyType& b) {
        // 自定义类型的交换操作
    }
}

通过在 std 命名空间中提供自定义类型 MyType 的特化版本,我们可以重载 std::swap 函数,以便在交换自定义类型对象时执行特定的交换操作。

以下是使用 std::swap 进行值交换的示例:

#include <algorithm>
#include <iostream>

int main() {
    int a = 10;
    int b = 20;

    std::cout << "Before swap: a = " << a << ", b = " << b << std::endl;

    std::swap(a, b);

    std::cout << "After swap: a = " << a << ", b = " << b << std::endl;

    return 0;
}

在上述示例中,我们定义了两个整数变量 a 和 b,并分别初始化为 10 和 20。然后,我们使用 std::swap 函数交换了 a 和 b 的值。

输出结果为:

Before swap: a = 10, b = 20
After swap: a = 20, b = 10

通过使用 std::swap,我们可以方便地交换两个对象的值,而无需显式编写临时变量或自定义交换函数。这在许多情况下都非常有用,例如在排序算法、容器操作等需要交换值的场景中。自c++11起,标准库提供了针对array的重载版本。另外,对于自定义类型,可以通过重载 operator= 实现自定义的交换操作。

总结起来,std::swap 是 C++ 标准库提供的通用交换函数,可以用于交换不同类型的对象。对于内置类型和标准库提供的类型,已经有默认的特化版本定义。对于自定义类型,我们可以通过特化版本或自定义的 swap 函数来实现自定义类型的交换操作。

比较操作符

在 C++11 中,可以使用以下操作符来比较两个对象的大小关系:

!=(不等于):用于检查两个对象是否不相等。
>(大于):用于检查一个对象是否大于另一个对象。
<(小于):用于检查一个对象是否小于另一个对象。
>=(大于等于):用于检查一个对象是否大于或等于另一个对象。
<=(小于等于):用于检查一个对象是否小于或等于另一个对象。

这些操作符可以用于内置类型(例如整数、浮点数等)和用户自定义类型,前提是对应的操作符重载已经定义或者对象支持相关的比较操作。

以下是一个示例,展示如何使用这些操作符来比较两个整数:

#include <iostream>

int main() {
    int a = 10;
    int b = 5;

    if (a != b) {
        std::cout << "a is not equal to b" << std::endl;
    }

    if (a > b) {
        std::cout << "a is greater than b" << std::endl;
    }

    if (a < b) {
        std::cout << "a is less than b" << std::endl;
    }

    if (a >= b) {
        std::cout << "a is greater than or equal to b" << std::endl;
    }

    if (a <= b) {
        std::cout << "a is less than or equal to b" << std::endl;
    }

    return 0;
}

输出结果为:

a is not equal to b
a is greater than b
a is not less than b
a is greater than or equal to b
a is not less than or equal to b

在上述示例中,我们比较了两个整数 a 和 b,并根据它们的大小关系输出相应的消息。注意,如果要比较自定义类型的对象,需要重载相应的比较操作符。

7.Class ratio<>

std::ratio 是 C++ 标准库中的一个模板类,用于表示有理数比例。它位于 头文件中。

std::ratio 模板类的定义如下:


template <intmax_t Num, intmax_t Denom = 1>
class ratio;

其中,Num 表示分子,Denom 表示分母,默认值为 1。Num 和 Denom 都必须是整数类型。

std::ratio 模板类提供了一种在编译时表示有理数比例的方式,它可以用于进行单位转换、计算比例关系等操作。它的主要作用是提供一种编译时的静态类型来表示常见的比例关系,而不需要在运行时进行计算。

以下是使用 std::ratio 的示例:

#include <iostream>
#include <ratio>

int main() {
    using one_half = std::ratio<1, 2>;
    using one_third = std::ratio<1, 3>;
    using two_thirds = std::ratio_add<one_third, one_third>;

    std::cout << "1/2 = " << one_half::num << "/" << one_half::den << std::endl;
    std::cout << "1/3 = " << one_third::num << "/" << one_third::den << std::endl;
    std::cout << "1/3 + 1/3 = " << two_thirds::num << "/" << two_thirds::den << std::endl;

    return 0;
}

输出结果为:

1/2 = 1/2
1/3 = 1/3
1/3 + 1/3 = 2/3

在这个示例中,我们定义了三个 std::ratio 类型的别名:one_half 表示 1/2,one_third 表示 1/3,two_thirds 表示 1/3 + 1/3。

通过访问 std::ratio 类的 num 和 den 静态成员变量,我们可以获取有理数比例的分子和分母,并进行输出。

运算式

在这里插入图片描述

预定义单位

C++ 标准库中的 头文件提供了一些预定义的 std::ratio 单位,用于表示常见的比例关系
在这里插入图片描述
这些预定义单位使得在表示物理量时更加方便,可以直接使用它们进行单位转换和比例计算。例如,std::kilo 表示千,可以将一个值乘以 std::kilo 来将其转换为千倍。

需要注意的是,std::ratio 是一个编译时计算的类型,它的值在编译时确定,并且不支持运行时的算术运算。它主要用于在编译时进行单位转换和比例计算,例如在模板元编程和静态类型检查等方面有广泛的应用。

8.Clock 和timer

C++11 中引入了 头文件,提供了 Clock 和 Timer 相关的功能,用于测量时间和实现定时器。

Duration(时间段)

C++11 中的 头文件引入了 std::chrono::duration 类模板,用于表示时间间隔或持续时间。std::chrono::duration 是一个通用的时间量类,可以用于表示不同单位的时间间隔,例如秒、毫秒、微秒等。

std::chrono::duration 的模板参数包括两个部分:Rep 和 Period。Rep 表示时间间隔的底层类型,通常是一个算术类型(如 int、double 等),而 Period 表示时间间隔的单位。Period 是一个 std::ratio 类型的实例,用于表示分子和分母的比例关系,决定了时间间隔的单位。

以下是一个使用 std::chrono::duration 的示例:

#include <iostream>
#include <chrono>

int main() {
    // 定义一个持续时间为 5 秒的 duration
    std::chrono::duration<int> durationSeconds(5);

    // 定义一个持续时间为 2.5 秒的 duration
    std::chrono::duration<double> durationSecondsDouble(2.5);

    // 输出 duration 的数值和单位
    std::cout << "durationSeconds: " << durationSeconds.count() << " seconds" << std::endl;
    std::cout << "durationSecondsDouble: " << durationSecondsDouble.count() << " seconds" << std::endl;

    // 将 duration 转换为毫秒
    std::chrono::duration<int, std::milli> durationMilliseconds = std::chrono::duration_cast<std::chrono::duration<int, std::milli>>(durationSeconds);

    // 输出转换后的 duration 的数值和单位
    std::cout << "durationMilliseconds: " << durationMilliseconds.count() << " milliseconds" << std::endl;

    return 0;
}

在这个示例中,我们创建了两个不同类型的 std::chrono::duration 对象:一个是持续时间为 5 秒的整数类型的 duration,另一个是持续时间为 2.5 秒的双精度浮点类型的 duration。我们使用 count() 成员函数来获取 duration 的数值,并使用 std::chrono::duration_cast 进行单位转换。

输出结果为:

durationSeconds: 5 seconds
durationSecondsDouble: 2.5 seconds
durationMilliseconds: 5000 milliseconds

在这里插入图片描述在这里插入图片描述

通过使用 std::chrono::duration,可以方便地对时间间隔进行计算、转换和表示,而不需要手动管理不同单位之间的转换。

Clock(时钟)

Clock 是一个时间测量的基准。C++11 提供了三种类型的时钟:

  • std::chrono::system_clock:用于表示系统的当前时间。
  • std::chrono::steady_clock:用于表示相对稳定的时间,不会受到系统时间的影响。
  • std::chrono::high_resolution_clock:提供高精度的时钟,可能是 system_clock 或 steady_clock 的别名。

这些时钟提供了 now() 成员函数,用于获取当前时钟的时间点。

以下是使用 std::chrono::steady_clock 的示例:

#include <iostream>
#include <chrono>

int main() {
    auto start = std::chrono::steady_clock::now();

    // 执行一些操作

    auto end = std::chrono::steady_clock::now();
    auto duration = end - start;

    std::cout << "耗时:" << std::chrono::duration<double>(duration).count() << " 秒" << std::endl;

    return 0;
}

在这个示例中,我们使用 std::chrono::steady_clock 获取了开始和结束的时间点,并计算了它们之间的时间差,得到了程序的执行时间。
在这里插入图片描述

Timer(定时器)

C++11 没有直接提供定时器的标准库类,但你可以使用 Clock 和一些其他的函数来实现定时器功能。例如,你可以使用 std::this_thread::sleep_for() 函数来让线程休眠一段时间实现简单的定时器功能。

以下是一个使用 std::this_thread::sleep_for() 实现定时器的示例:

#include <iostream>
#include <chrono>
#include <thread>

int main() {
    int count = 0;
    int target = 5;

    while (count < target) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        count++;
        std::cout << "定时器触发:" << count << std::endl;
    }

    std::cout << "定时器结束" << std::endl;

    return 0;
}

在这个示例中,我们使用 std::this_thread::sleep_for() 函数来让程序休眠 1 秒钟,并输出定时器触发的次数。程序会在计数达到目标值时结束定时器。

需要注意的是,定时器的实现方式可能因操作系统和编译器而有所不同。以上示例仅提供了一种简单的实现方式,实际应用中可能需要更复杂的定时器功能,可以根据具体需求进行扩展和优化。
在这里插入图片描述

C中的函数

原本在< time.h >内的定义现在都被纳入了< ctime >
在这里插入图片描述

Timepoint与日历时间的转换

在 C++11 的 头文件中,可以使用 std::chrono::time_point 类模板来表示时间点(Time Point)。时间点是一个特定时刻的抽象概念,与日历时间(Calendar Time)相对应。

要在时间点和日历时间之间进行转换,可以使用以下函数和类型:

  • std::chrono::system_clock:std::chrono::system_clock 是一个时钟类型,用于表示系统的当前时间。可以使用它来获取当前的日历时间。

  • std::chrono::time_point:std::chrono::time_point 是一个表示时间点的类模板。可以使用它来存储和操作时间点的值。

  • std::chrono::duration:std::chrono::duration 是一个表示时间间隔的类模板。可以使用它来计算时间点之间的差异。

以下是时间点和日历时间之间的转换示例:

#include <iostream>
#include <chrono>
#include <ctime>

int main() {
    // 获取当前的日历时间
    std::time_t currentTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

    // 将日历时间转换为时间点
    std::chrono::time_point<std::chrono::system_clock> timePoint = std::chrono::system_clock::from_time_t(currentTime);

    // 将时间点转换为日历时间
    std::time_t convertedTime = std::chrono::system_clock::to_time_t(timePoint);

    // 输出转换后的日历时间
    std::cout << "Converted time: " << std::asctime(std::localtime(&convertedTime));

    return 0;
}

在这个示例中,我们首先使用 std::chrono::system_clock::now() 获取当前的时间点,然后使用 std::chrono::system_clock::to_time_t() 将时间点转换为日历时间(std::time_t 类型)。接着,我们使用 std::chrono::system_clock::from_time_t() 将日历时间转换回时间点。最后,我们使用 std::asctime() 将转换后的日历时间输出到标准输出流。

需要注意的是,时间点和日历时间的精度和范围可能会有所不同。时间点通常具有更高的精度和更大的范围,而日历时间受限于 std::time_t 类型的精度和范围。

使用时间点和日历时间之间的转换,可以方便地在不同的时间表示之间进行转换和操作,以满足不同的需求。

计时器常在线程中使用,这一部分在后面的线程章节详细描述

9.一些重要头文件

<cstddef>

<cstddef> 头文件定义了一些与大小和指针操作相关的类型和函数
在这里插入图片描述

<cstdlib>

头文件定义了一些常见的库函数,如内存管理函数(如 malloc 和 free)、类型转换函数(如 atoi 和 atof)、随机数函数(如 rand 和 srand)以及其他一些常见的函数。
在这里插入图片描述

<cstring>

<cstring> 头文件定义了一些与字符串操作相关的函数和类型,如字符串复制函数(如 strcpy 和 strncpy)、字符串连接函数(如 strcat 和 strncat)、字符串比较函数(如 strcmp 和 strncmp)以及其他一些字符串处理函数。
在这里插入图片描述

示例

#include <iostream>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <string>

int main() {
    // 使用 cstddef 定义的类型
    std::size_t size = 10;
    std::ptrdiff_t diff = 5;
    std::nullptr_t nullPtr = nullptr;

    // 使用 cstdlib 的库函数
    int randomNumber = std::rand();
    std::cout << "Random number: " << randomNumber << std::endl;

    // 使用 cstring 的字符串操作函数
    char str1[] = "Hello";
    char str2[10];
    std::strcpy(str2, str1);
    std::strcat(str2, " World");
    std::cout << "Concatenated string: " << str2 << std::endl;

    // 使用 string 类进行字符串操作
    std::string s1 = "Hello";
    std::string s2 = "World";
    std::string s3 = s1 + " " + s2;
    std::cout << "Concatenated string: " << s3 << std::endl;

    return 0;
}

这个示例演示了如何使用 、、 和 头文件进行基本类型、库函数和字符串操作。注意,在使用 C++ 中的字符串时,推荐使用 std::string 类来代替传统的 C 风格字符串(以字符数组表示)以获得更安全和方便的字符串操作功能。

  • 第五章完

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/652768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flutter如何获取屏幕的分辨率和实际画布的分辨率

Flutter如何获取分辨率 在Flutter中&#xff0c;你可以使用MediaQuery来获取屏幕的分辨率和实际画布的分辨率。 要获取屏幕的分辨率&#xff0c;你可以使用MediaQuery.of(context).size属性&#xff0c;它返回一个Size对象&#xff0c;其中包含屏幕的宽度和高度。下面是一个获…

Redis中常见的一些问题

缓存穿透问题 什么是缓存穿透&#xff1f; 例如当我们根据id查询一个数据的时候&#xff0c;但是这个数据本身不存在或者已经被删除之后&#xff0c;缓存中不存在&#xff0c;就会去查询数据库&#xff0c;但是不存在的数据不会缓存到数据库中&#xff0c;那么一旦大量的这个请…

层序遍历的应用——判断二叉树是否为完全二叉树

思维导图&#xff1a; 一&#xff0c;完全二叉树的特点 假如我们现在有一颗完全二叉树&#xff0c;那它应该长什么样呢&#xff1f; 它应该长这样&#xff1a; 这样&#xff1a; 这样&#xff1a; 如果不是一…

6 种方式读取 Springboot 的配置,老鸟都这么玩(原理+实战)

大家好&#xff0c;我是小富&#xff5e; 从配置文件中获取属性应该是SpringBoot开发中最为常用的功能之一&#xff0c;但就是这么常用的功能&#xff0c;仍然有很多开发者在这个方面踩坑。 我整理了几种获取配置属性的方式&#xff0c;目的不仅是要让大家学会如何使用&#…

Exiv2 —— exiv2介绍及下载搭建环境(Vs2017)

Exiv2介绍 Exiv2 是一个跨平台C库和一个命令行实用程序&#xff0c;用于管理图像元数据。它提供对Exif&#xff0c;IPTC和XMP元数据以及ICC配置文件的快速简便的读写访问。 嵌入到各种格式的数字图像中。 Exiv2 作为免费软件提供&#xff0c;用于许多项目 包括KDE和Gnome Deskt…

chatgpt赋能python:Python自动化脚本编写——让工作更高效

Python自动化脚本编写——让工作更高效 在当今的工作中&#xff0c;自动化脚本已经成为了一个不可或缺的工具。而Python作为一门脚本语言&#xff0c;它的开源、易用以及强大的库使得它成为了很多人使用自动化脚本的首选语言。 在本文中&#xff0c;我们将会探讨如何使用Pyth…

ChatGPT 指南:角色扮演让回答问题更专业

让 ChatGPT 进行角色扮演 Act as ...&#xff0c;比如&#xff0c;律师、内科医生、心理医生、运动教练、哲学家、翻译、平面设计师、IT 工程师等等&#xff0c;从而才能让 ChatGPT 从这个角色角度来分析我们的问题&#xff0c;不然&#xff0c;它的回答可能会过于广泛。 下面以…

Vue中如何进行自动化测试与端到端测试(E2E测试)

Vue中如何进行自动化测试与端到端测试&#xff08;E2E测试&#xff09; Vue.js是一种流行的前端JavaScript框架&#xff0c;用于构建现代的单页应用程序。在Vue.js中&#xff0c;测试是一个非常重要的主题。测试可以确保代码的正确性&#xff0c;使代码更加可靠和可维护。在这…

p-tuing和Lora的区别

一、前言 自从chatgpt的爆火&#xff0c;也同时引发了国内大模型的热潮&#xff0c;像百度出了文心一言、阿里出了通义千问等&#xff0c;但是这些大模型并未开源&#xff0c;国内外开源的中等规模的模型有meta的LLaMA&#xff0c;斯坦福基于LLaMA微调的Alpaca&#xff0c;国内…

小程序开发的前沿趋势和技术

在过去的一年里&#xff0c;小程序已成为移动互联网行业最热门的话题之一。小程序已经改变了许多行业。那么&#xff0c;下一个小程序开发趋势是什么&#xff1f;下面我们就来分析一下。 随着微信小程序的开放和推广&#xff0c;小程序开发企业正在大力发展并逐渐从技术方面进…

【2023最新版】黑客零基础入门(全网最全)从零基础到进阶,学完这一篇就够了

学前感言 1.这是一条需要坚持的道路&#xff0c;如果你只有三分钟的热情那么可以放弃往下看了。2.多练多想&#xff0c;不要离开了教程什么都不会&#xff0c;最好看完教程自己独立完成技术方面的开发。3.有问题多google,baidu…我们往往都遇不到好心的大神&#xff0c;谁会无…

【Qt】使用libmodbus实现ModBusTcp

这里写目录标题 下载编译使用DemoQModbusTcpClient Demo:参照:Qt自带QModbusTcpClient,换个电脑就不好使了,换libmodbus 下载 可以去github下载 链接: https://pan.baidu.com/s/13lgEZ59Dt5M7zmTJNpfKvg?pwd=yzfm 提取码: yzfm 下载libmodbus 并解压 编译 进入该目录下…

智造零距离:工程师走访华秋深圳 PCB 工厂,观摩高可靠板制造流程

6月11日&#xff0c;来自硬十、是德、灵明光子、兆易创新、汇顶科技、中诺通讯等公司的近20位工程师走访了华秋深圳PCB工厂。华秋工艺经理余宁带领考察团参观了工厂的生产线&#xff0c;近距离观摩了PCB的制造流程。 参观环节正式开始前&#xff0c;工厂安排专家介绍PCB制造的详…

SpringBatch从入门到实战(四):执行上下文和单步骤重启

一&#xff1a;执行上下文 1.1 JobContext 作业上下文 JobContext 绑定 JobExecution 执行对象&#xff0c;为Job作业执行提供执行环境(上下文)。 1.2 StepContext 步骤上下文 StepContext 绑定 StepExecution 执行对象&#xff0c;为Step步骤执行提供执行环境(上下文)。 1…

Ansible playbook ----- 剧本

playbooks 本身由以下各部分组成 &#xff08;1&#xff09;Tasks&#xff1a;任务&#xff0c;即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行 &#xff08;2&#xff09;Variables&#xff1a;变量 &#xff08;3&#xff09;Templates&#xff1a;模…

Ubuntu 20.04 LTS 安装教程

Ubuntu 20.04 LTS 以及必要软件的安装教程 1、Ubuntu 系统下载2、制作U盘安装盘3、安装Ubuntu系统4、必要软件安装4.1、调整系统时间4.2、安装搜狗中文输入法4.3、anaconda 安装4.4、安装 terminator4.4、安装 nvidia 驱动 1、Ubuntu 系统下载 官方桌面版下载&#xff1a;https…

电力监控系统软件的设计与功能介绍

安科瑞虞佳豪 风吹麦浪&#xff0c;炎夏将至。随着气温节节攀升&#xff0c;社会用电需求越来越大&#xff0c;给电网安全和电力供应带来挑战。国网诸城市供电公司扛牢电力保供责任&#xff0c;迎难而上&#xff0c;筑牢强电网、保安全、防大汛“三部曲”&#xff0c;全力保障…

数据库优化可以从哪些维度入手?(建议收藏)

当有人问你如何对数据库进行优化时&#xff0c;很多人第一反应想到的就是SQL优化&#xff0c;如何创建索引&#xff0c;如何改写SQL&#xff0c;他们把数据库优化与SQL优化划上了等号。 当然这不能算是完全错误的回答&#xff0c;只不过思考的角度稍微片面了些&#xff0c;太“…

还在争论WPS、Office哪个更好用?3款云办公平台深度评测!

随着当下智能化产业发展&#xff0c;办公系统也逐渐升级。像答主所在公司就已经使用了简道云办公平台&#xff0c;真正实现无纸化办公&#xff0c;极大地提升了工作效率。什么是云办公平台&#xff1b;相较于传统办公平台&#xff0c;云办公平台又哪些独特的优势呢&#xff0c;…

Vue-props配置

props配置 像el&#xff0c;data&#xff0c;watch&#xff0c;methods…都是vue的配置项&#xff0c;props也是一个配置项 props主要用来实现组件复用&#xff0c;并且动态绑定数据,它有3种使用方式&#xff0c;下面一一说明 通过案例进行分析使用props配置学习如何使用以及…