C++11 学習ノート (4) - 一般ツール (パート 2)

長すぎるので2回に分けて書きましょう、
本は続きます

4. 数値の極値

std::numeric_limits は、C++ 標準ライブラリで定義されているテンプレート クラスで、ヘッダー ファイルにあります。さまざまな数値型のプロパティと極値に関する情報を提供します。この情報は、プログラムで数値処理を実行するときに、特定のタイプの数値範囲、精度、その他の数値関連の特性を理解するのに役立ちます。

最小精度

タイプ 最小の長さ
文字 1バイト
短い整数 2バイト
整数 2バイト
長い整数 4バイト
長い長い整数 8バイト
浮く 4バイト
ダブル 8バイト
ロングダブル 8バイト

一般的な 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 を特殊化することで、特定の型のカスタム制限値と属性情報を提供できます。

以下は、カスタム タイプ MyType のカスタム制限値と属性情報を提供するために std::numeric_limits を特殊化する方法を示す例です。

#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 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;
}

この方法では、複数のパラメータ タイプを含めるのに必要な実装は 2 つだけです。

一般的なタイプを処理する

共通型とは、一貫した型を操作して返すことができる型のグループの中で最も低い共通型を指します。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;
}

上記の例では、2 つのパラメーター value1 と value2 を受け入れ、std::common_type を使用してこれら 2 つのパラメーターの最も低い共通タイプ CommonType を取得するプロセス関数テンプレートを定義します。次に、CommonType を使用して変数 result を宣言し、value1 と value2 を追加して、結果を result に代入します。最後に、結果をコンソールに出力します。

main 関数では、process 関数を呼び出して、整数や浮動小数点数などのさまざまなタイプのパラメーターを渡します。std::common_type は、最も低い共通型を自動的に推定し、その結果に対して対応する型変換と演算を実行します。

std::common_type を利用することで、型の異なるパラメータの集合を処理し、最も低い共通型を取得することで、共通型の処理を実現します。これは、汎用プログラミングやテンプレート メタプログラミングで、さまざまなタイプの組み合わせの操作を処理するのに役立ちます。

その他の操作

すべてのタイプに

ここに画像の説明を挿入

クラスクラス用

ここに画像の説明を挿入

ブール値とすべての文字は整数クラスとして扱われることに注意してください。

型関係をチェックする

ここに画像の説明を挿入

タイプ変更

ここに画像の説明を挿入

他の

ここに画像の説明を挿入

参照ラッパー

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;
}

上の例では、参照パラメータを受け取り、それをインクリメントするインクリメント関数を定義しました。main 関数では、std::reference_wrapper オブジェクト ref を作成し、それに num の参照を渡します。次に、インクリメント関数を呼び出して、実際には num への参照である ref を渡します。最後に、num の値を出力し、値が増加していることを確認します。

std::reference_wrapper を使用すると、参照型をオブジェクトとして渡して操作できるため、より便利で柔軟な参照セマンティクスが提供されます。汎用プログラミング、関数オブジェクト、STL アルゴリズムなどのシナリオでよく使用されます。

関数型ラッパー

std::function は、C++ 標準ライブラリで提供されるクラス テンプレートであり、さまざまな種類の呼び出し可能なオブジェクトをカプセル化し、一貫した呼び出しインターフェイスを提供するために使用されます。

std::function のクラス テンプレートは次のように定義されます。

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

ここで、R は戻り値の型、Args... は引数の型のリストです。

std::function を使用すると、関数ポインター、関数オブジェクト、メンバー関数ポインター、ラムダ式など、さまざまな種類の呼び出し可能なエンティティをラップできる関数オブジェクトを作成できます。

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 があります。次に、関数型が int(int, int) である std::function オブジェクト func を宣言します。

まず add 関数を func に割り当て、次に func を使用して add 関数を呼び出し、結果を出力します。次に、std::bind を使用して Foo クラスのメンバー関数 multiply を func にバインドし、Foo クラスのオブジェクト ポインターと 2 つのプレースホルダーをパラメーターとして渡します。最後に、func を使用して Foo::multiply を呼び出し、結果を出力します。


プレースホルダは、関数オブジェクトのパラメータ位置を占める C++ 標準ライブラリの特別なオブジェクトです。関数オブジェクト内のプレースホルダーは、実際に呼び出されたときにこの位置のパラメーターが対応する値に置き換えられることを示します。

std::bind の使用では、プレースホルダー std::placeholders::_1、std::placeholders::_2、std::placeholders::_3、およびさらに連続して増加するプレースホルダー _4、_5 などを使用して、関数オブジェクトのパラメーターの位置を識別します。プレースホルダーを使用すると、実際のパラメーター値を指定しなくても、関数をバインドするときにパラメーターの位置を指定できます。

サンプル コードでは、2 つのプレースホルダー std::placeholders::_1 と std::placeholders::_2 を使用します。

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

ここでは、Foo::multiply メンバー関数を func にバインドし、2 つのプレースホルダーを使用してパラメーターの位置を指定します。これは、 func を呼び出すと、プレースホルダーの代わりに引数が渡されることを意味します。

実際に func(3, 4) を呼び出すと、プレースホルダー std::placeholders::_1 は最初のパラメーター (3) に対応し、プレースホルダー std::placeholders::_2 は 2 番目のパラメーター (4) に対応します。したがって、パラメーター 3 と 4 は実際のパラメーターとして Foo::multiply メンバー関数に渡されます。

プレースホルダーを使用すると、特に関数オブジェクトのバインディングとパラメーターの位置マッピングの点で、関数オブジェクトをより柔軟にすることができます。これにより、パラメーターの受け渡しを延期し、関数オブジェクトを呼び出すときにパラメーター値を動的に提供することができます。

プレースホルダーの数と位置は、関数オブジェクトのパラメーターの数と位置と一致する必要があることに注意してください。そうしないと、不正なパラメータの受け渡しやコンパイル エラーが発生します。

この例では、プレースホルダーを使用して、バインドされた関数オブジェクトを foo オブジェクトおよびパラメーターの位置に関連付けます。このようにして、バインドされた関数オブジェクトを呼び出すと、foo オブジェクトの乗算関数が呼び出され、対応する位置引数が関数に渡されます。


std::function を通じて、さまざまな種類の呼び出し可能なオブジェクトを 1 つの統合オブジェクトにカプセル化し、それらを統一された方法で呼び出すことができます。これにより、柔軟性と汎用性が向上し、関数オブジェクトの使用がより便利で拡張可能になります。

6. ヘルパー関数

最大値と最小値

すべての minmax() 関数と初期値列を持つすべての関数は c++11 から始まります
ここに画像の説明を挿入。ヘッダー ファイルで関数を使用するときは、通常、要素の順序を決定したり、他の条件を満たすために比較関数 (または述語) を指定する必要があります。比較関数は、2 つの引数を受け取り、2 つの要素の順序を比較するブール値を返す呼び出し可能なオブジェクトです。

カスタム比較

比較関数を使用した並べ替えの例を次に示します。


#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 になります。

比較関数をカスタマイズすることで、特定の条件に従って要素を並べ替えたり比較したりできます。これは、カスタムの並べ替え順序、特定のルールによる要素のフィルター処理など、多くのアルゴリズムや操作で役立ちます。さまざまなニーズに応じて、特定の並べ替えや比較ロジックを満たすさまざまな比較関数を作成できます。

2 つの値を交換する

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 には、組み込み型と標準ライブラリによって提供される型のデフォルトの特殊化定義がすでにあります。

さらに、カスタム型の場合、型の特殊なバージョンを定義するか、カスタム スワップ関数を提供することで、カスタム型のスワップ操作を実現できます。例えば:

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;
}

上の例では、2 つの整数変数 a と b を定義し、それぞれ 10 と 20 に初期化しました。次に、std::swap 関数を使用して a と b の値を交換しました。

出力は次のとおりです。

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

std::swap を使用すると、一時変数やカスタム スワップ関数を明示的に記述せずに、2 つのオブジェクトの値を簡単にスワップできます。これは、ソートアルゴリズムやコンテナ操作など、値を交換する必要がある多くの状況で非常に役立ちます。C++11 以降、標準ライブラリは array のオーバーロードされたバージョンを提供しますさらに、ユーザー定義型の場合、operator= をオーバーロードすることでユーザー定義の交換操作を実装できます。

要約すると、std::swap は C++ 標準ライブラリによって提供される一般的な交換関数であり、異なる型のオブジェクトを交換するために使用できます。組み込み型と標準ライブラリによって提供される型のデフォルトの特殊化定義がすでに存在します。カスタム タイプの場合、特殊なバージョンまたはカスタム スワップ関数を通じてカスタム タイプのスワップ操作を実装できます。

比較演算子

C++11 では、次の演算子を使用して 2 つのオブジェクトのサイズ関係を比較できます。

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

これらの演算子は、対応する演算子のオーバーロードが定義されているか、オブジェクトが関連する比較演算をサポートしている場合に限り、組み込み型 (整数、浮動小数点数など) およびユーザー定義型で使用できます。

これらの演算子を使用して 2 つの整数を比較する方法を示す例を次に示します。

#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

上の例では、2 つの整数 a と b を比較し、それらの大小関係に基づいて対応するメッセージを出力します。カスタム タイプのオブジェクトを比較する場合は、対応する比較演算子をオーバーロードする必要があることに注意してください。

7.クラス比率<>

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 型に 3 つのエイリアスを定義します。1/2 の場合は one_half、1/3 の場合は one_third、1/3 + 1/3 の場合は two_threes です。

std::ratio クラスの静的メンバー変数 num と den にアクセスすることで、有理数の比の分子と分母を取得して出力できます。

表現

ここに画像の説明を挿入

事前定義された単位

C++ 標準ライブラリのヘッダー ファイルには、一般的な比例関係を表すために使用される事前定義された std::ratio 単位がいくつか用意されています。これらの事前定義された単位を使用すると、
ここに画像の説明を挿入
物理量を表現するのがより便利になり、単位変換や比率の計算に直接使用できます。たとえば、 std::kilo は 1,000 を表し、値に std::kilo を乗算して 1,000 倍に変換できます。

std::ratio はコンパイル時に計算される型であり、その値はコンパイル時に決定され、実行時の算術演算をサポートしないことに注意してください。これは主にコンパイル時の単位変換と比率計算に使用され、たとえば、テンプレートのメタプログラミングや静的型チェックに幅広い用途があります。

8. 時計とタイマー

ヘッダー ファイルは、時間を測定しタイマーを実装するための Clock と Timer に関連する関数を提供するために C++11 で導入されました。

期間(期間)

C++11 のヘッダー ファイルでは、時間間隔または期間を表すための std::chrono::duration クラス テンプレートが導入されています。std::chrono::duration は、秒、ミリ秒、マイクロ秒などのさまざまな単位で時間間隔を表すために使用できる一般的な時間量クラスです。

std::chrono::duration のテンプレート パラメーターは、R​​ep と Period の 2 つの部分で構成されます。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;
}

この例では、異なる型の 2 つの std::chrono::duration オブジェクトを作成します。つまり、持続時間が 5 秒の integer 型の持続時間と、持続時間が 2.5 秒の double 型の持続時間です。count() メンバー関数を使用して期間の値を取得し、単位変換には std::chrono::duration_cast を使用します。

出力は次のとおりです。

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

ここに画像の説明を挿入ここに画像の説明を挿入

std::chrono::duration を使用すると、異なる単位間の変換を手動で管理することなく、時間間隔を簡単に計算、変換、および表現できます。

時計

時計は時間を計測するための基準です。C++11 では、次の 3 種類のクロックが提供されます。

  • std::chrono::system_lock: システムの現在時刻を表すために使用されます。
  • std::chrono::steady_ Clock: 比較的安定した時間を表すために使用され、システム時間の影響を受けません。
  • std::chrono::high_resolution_lock: 高精度クロックを提供します。これは、system_ Clock またはsteady_ Clock のエイリアスである可能性があります。

これらの時計は、現在の時計の時刻を取得するための now() メンバー関数を提供します。

std::chrono::steady_lock を使用した例を次に示します。

#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 を使用して開始時刻と終了時刻を取得し、それらの間の時間差を計算してプログラムの実行時間を取得します。
ここに画像の説明を挿入

タイマー

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> に含まれています。
ここに画像の説明を挿入

タイムポイントとカレンダー時間の間の変換

C++11 のヘッダー ファイルでは、std::chrono::time_point クラス テンプレートを使用して時点 (Time Point) を表現できます。時点とは、暦時間に対応する特定の瞬間の抽象的な概念です。

ある時点とカレンダー時刻の間で変換するには、次の関数と型を使用できます。

  • std::chrono::system_lock: std::chrono::system_lock は、システムの現在時刻を表すために使用されるクロック タイプです。現在のカレンダー時刻を取得するために使用できます。

  • 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_lock::now() を使用して現在の時点を取得し、次に std::chrono::system_lock::to_time_t() を使用して時点をカレンダー時刻 (std::time_t 型) に変換します。次に、std::chrono::system_lock::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++ で文字列を操作する場合、より安全で便利な文字列操作関数を実現するために、従来の C スタイルの文字列 (文字配列として表される) の代わりに std::string クラスを使用することをお勧めします。

  • 第五章の終わり

おすすめ

転載: blog.csdn.net/qq_44616044/article/details/131223759