私たちのチームは10年以上前のC ++コードベースで作業しており、最近C ++ 17コンパイラに切り替えました。そこで、コードを最新化する方法を探しています。YouTubeでのカンファレンストークで、const char*
グローバル文字列をに置き換えるという提案を聞きましたconstexpr string_view
。
const char*
コードにはこのようなグローバル文字列定数が多数含まれているので、知っておく必要のある問題や潜在的な問題がないか確認したいのですが。
私たちのチームは10年以上前のC ++コードベースで作業しており、最近C ++ 17コンパイラに切り替えました。そこで、コードを最新化する方法を探しています。YouTubeでのカンファレンストークで、const char*
グローバル文字列をに置き換えるという提案を聞きましたconstexpr string_view
。
const char*
コードにはこのようなグローバル文字列定数が多数含まれているので、知っておく必要のある問題や潜在的な問題がないか確認したいのですが。
回答:
これらの問題は、認識しておく価値があります。
std::string_view
null
終了する必要はありません。そのため、一部const char*
をstring_view
で置き換え、以前にnull
終了したchar*
部分文字列の構成をstring_view
via std::string_view::substr
で置き換える場合、基本となるポインタを、null
終了文字列を期待するAPIに渡すことはできません。例(UBはありませんが、これも簡単に構築できます):
void legacy(const char *str) {
std::printf("%s\n", str);
}
constexpr std::string_view sv1 = "abcde";
constexpr std::string_view sv2 = sv1.substr(0, 2); // view on "ab"
legacy(sv2.data()); // Not intended: prints "abcde"
std::string
から暗黙的にを作成するconst char*
ことはできますが、を使用してそれを行うことはできませんstd::string_view
。これは、ディープコピーが内部で行われるべきではなく、明示的に要求された場合にのみ行われるという考え方です。例:
std::map<std::string, int> m;
constexpr std::string_view sv = "somekey";
constexpr const char *old = "somekey";
m[old] = 42; // works as expected
m[sv] = 42; // fails to compile
m[std::string(sv)] = 42; // be explicit, this is ok
const char*
プロジェクトでのグローバルインスタンスの既存の使用方法によっては、この動作をさまざまな場所で手動で行う必要がある場合があります。
someLegacyFct(std::string(sv).c_str())
、このバックエンドがどういうわけかポインタを保存する場合
const char*
コンストラクターを備えた独自の文字列クラス(わかっています...)したがって、std::string
fromの明示的な構築はstring_view
、私たちの場合は一貫しています。
std::string(sv).c_str()
APIに渡すために代わりに行うと思いますか?