コンテンツにスキップ

最終更新:2026-10-12

STL string 深入解析

C++を使うとき、ライブラリの基礎知識は比較的よく知られています。特にC++で文字列を作成するときに使うstd::stringは、古いCスタイルの「文字列」(ヌル文字で終端される文字配列)に対する改良であることは間違いありません。しかし、C++標準ライブラリはC++17とC++20で、より効率的なコードを書くのに役立つ、より便利なコンポーネントを導入しました。

ヘッダでは、std::basic_stringクラスはテンプレートクラスであり、さまざまな文字列型に対して特殊化を提供しています。よく使われる文字列のstd::string(すなわちstd::basic_string)や、ワイド文字列のstd::wstring(すなわちstd::basic_string)などです。

さらに、固定幅の特定の文字列として、std::u32string(すなわちstd::basic_string)やstd::u16string(すなわちstd::basic_string)もあります。

C++20ではchar8_tが導入され、これに伴ってstd::u8string(すなわちstd::basic_string)も登場しました。なぜchar8_tの導入がC++20まで待たなければならなかったのか私にはわかりません。そこで問題です。char16_tとchar32_tはどの標準に存在するでしょうか?コメント欄でお会いしましょう

C++11

C++11標準では、文字列処理は主にstd::stringクラスに依存していました。これは動的にメモリを割り当てる文字列クラスです。さらに、std::u32stringやstd::u16stringのような新しい固定幅の文字列型が導入され、Unicode文字の処理に対するより良いサポートが提供されました。

#include <iostream>
#include <string>

int main() {
    // 使用std::string
    std::string str = "Hello, C++11!";

    // 使用std::u32string和std::u16string
    std::u32string u32str = U"Hello, Unicode!";
    std::u16string u16str = u"Hello, Unicode!";

    std::cout << str << std::endl;
    std::wcout << u32str << std::endl;
    std::wcout << u16str << std::endl;

    return 0;
}

C++17

C++17ではヘッダが導入され、ヘッダの文字列型を使うための軽量な読み取り専用の代替手段が提供されました。これらの文字列ビューは、先に説明した文字列と類似しています。例えば、std::u32stringの版はstd::u32string_view(すなわちstd::basic_string_view)です。

これは、文字列を読み取る必要はあるが変更する必要はない関数で特に役立ちます。**関数のために文字列のコピーを作成する**のとは異なり、既存の文字列を単に参照すればよいのです!さらに、は非常に柔軟で、C++スタイルの文字列を文字列ビューに変換できるだけでなく、Cスタイルの文字列さえも文字列ビューに変換できます。以下はstd::string_viewの簡単な使い方を示す例です:

#include <iostream>
#include <string>
#include <string_view>

void printString(std::string_view str) {
  std::cout << str << std::endl;
}

int main() {
  std::string_view strv{"strv"}; // C++ string_view
  printString(strv);

  std::string str{"str"}; // C++ string
  printString(str);

  char cstr[] = "cstr"; // C-style string
  printString(cstr);

  return 0;
}

出力:

strv
str
cstr

この例では、printString関数がstd::string_viewを引数として取っています。これにより、文字列のコピーが一切作成されないため、この関数は非常に軽量かつ柔軟になり、CとC++スタイルの文字列を渡すことでさまざまな方法で使用できます。

C++20

C++20では、starts_with(…)やends_with(…)を含む新しい便利なメンバ関数が導入されました。名前が示す通り、これらの関数は文字列(または文字列ビュー)が特定の文字または特定のstd::string_viewで始まる/終わるかどうかを判定します。以下は簡単な例です:

#include <cassert>
#include <string>
#include <string_view>

int main() {
  const std::string str{"Hello World!"};

  assert(str.starts_with('H'));
  assert(str.ends_with('!'));

  assert(str.starts_with("Hello")); // 隐式转换为std::string_view
  assert(str.ends_with("World!")); // 隐式转换为std::string_view

  return 0;
}

C++23

C++23ではcontainsが導入され、文字列が指定された部分文字列を含むかどうかをチェックできます。

// 这是一个假设的C++23示例,实际上并不可用
#include <iostream>
#include <string>

int main() {
    std::string str = "C++23 introduces contains function.";

    if (str.contains("introduces")) {
        std::cout << "The string contains 'introduces'." << std::endl;
    } else {
        std::cout << "The string does not contain 'introduces'." << std::endl;
    }

    return 0;
}

https://en.cppreference.com/w/cpp/string/basic_string/contains

結論

新しいC++コードで文字列を扱うときは、コードをできるだけ柔軟かつメモリ効率よくすることを検討すべきです。の使用はこれらの努力に大いに役立ちます。さらに、starts_withやends_withのような最新の文字列メンバ関数の使用を検討すると、可読性が高く実装しやすい文字列パースコードが得られます。そしてC++23によってcontainsの判定がより簡単になり、どんどんモダンになっています。

関連トピック

コメント