グローバルconst char []をconstexpr string_viewに置き換える落とし穴はありますか?


17

私たちのチームは10年以上前のC ++コードベースで作業しており、最近C ++ 17コンパイラに切り替えました。そこで、コードを最新化する方法を探しています。YouTubeでのカンファレンストークで、const char*グローバル文字列をに置き換えるという提案を聞きましたconstexpr string_view

const char*コードにはこのようなグローバル文字列定数が多数含まれているので、知っておく必要のある問題や潜在的な問題がないか確認したいのですが。

回答:


15

これらの問題は、認識しておく価値があります。

  1. std::string_viewnull終了する必要はありません。そのため、一部const char*string_viewで置き換え、以前にnull終了したchar*部分文字列の構成をstring_viewvia 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" 
  2. 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*プロジェクトでのグローバルインスタンスの既存の使用方法によっては、この動作をさまざまな場所で手動で行う必要がある場合があります。


ゼロ以外の終了は間違いなく問題です。次に、SVを確認する必要があります。std::string(sv).c_str()APIに渡すために代わりに行うと思いますか?
darune

@daruneこれはオプションですが、APIの有効期間の仮定を確認する必要がありますよね?!あなたが行ってsomeLegacyFct(std::string(sv).c_str())、このバックエンドがどういうわけかポインタを保存する場合
lubgr

それは正しい-その寿命の仮定がある場合にのみ
-darune

2番目の問題は、「幸運なことに」私たちにとって大した問題にはなりません。私たちの会社のフレームワークには、明示的なconst char*コンストラクターを備えた独自の文字列クラス(わかっています...)したがって、std::stringfromの明示的な構築はstring_view、私たちの場合は一貫しています。
PixelSupreme
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.