2

const char *を受け入れ、関数ProcessStringを使用する関数を変更しています。ProcessStringは、nullで終了する文字バッファーをchar*として予期する関数です。以下の関数シグネチャで定義されているように、バッファ内の文字は変更される場合と変更されない場合があります。「ギャップを埋める」ために、一時的なstd :: string:を使用しています。

void ProcessString( char* str );

void SomeFunction( const char* str )
{
  string temp(str);
  ProcessString( &temp[0] );
}

私の主な質問は、std :: string :: operator []の保証と、上記の&temp[0]によって返されるアドレスがchar*として使用可能なnullで終了するバッファーであるかどうかについてです。第二に、そして非常に第二に、これを行うためのより良い方法はありますか?

私はC++03を使用しています。

4

3 に答える 3

5

これは、C++11でのみ明確に定義された動作をします。以前の標準でstd::stringは、内部バッファの連続ストレージを保証していませんでした。

ただし、そのコードはC ++ 11では完全に問題ありませんが、より慣用的なアプローチはを使用することstd:vector<char>です。これにより、C++03以降の連続したストレージが保証されます。

void ProcessString(char* str);

void SomeFunction(char const* str)
{
    // + 1 for terminating NUL
    std::vector<char> temp(str, str + std::strlen(str) + 1);
    ProcessString(&temp[0]); // or temp.data() in C++11
}
于 2012-03-15T21:32:57.273 に答える
1

この種の問題に直面するために小さなクラスを作成し、RAIIイディオムを実装しました。

class DeepString
{
        DeepString(const DeepString& other);
        DeepString& operator=(const DeepString& other);
        char* internal_; 

    public:
        explicit DeepString( const string& toCopy): 
            internal_(new char[toCopy.size()+1]) 
        {
            strcpy(internal_,toCopy.c_str());
        }
        ~DeepString() { delete[] internal_; }
        char* str() const { return internal_; }
        const char* c_str()  const { return internal_; }
};

そして、あなたはそれを次のように使うことができます:

void aFunctionAPI(char* input);

//  other stuff

aFunctionAPI("Foo"); //this call is not safe. if the function modified the 
                     //literal string the program will crash
std::string myFoo("Foo");
aFunctionAPI(myFoo.c_str()); //this is not compiling
aFunctionAPI(const_cast<char*>(myFoo.c_str())); //this is not safe std::string 
                                                //implement reference counting and 
                                                //it may change the value of other
                                                //strings as well.
DeepString myDeepFoo(myFoo);
aFunctionAPI(myFoo.str()); //this is fine

クラスDeepStringを呼び出したのは、既存の文字列の深くて一意のコピー(DeepStringはコピーできません)を作成しているためです。

于 2012-03-15T21:34:34.850 に答える
0

const char*aからaに移動する必要がある場合は、 strdupchar *を使用して、ProcessStringが完了したときにバッファを解放してみませんか?

通過するstd::stringことは私には不必要に思えます。

于 2012-03-15T21:31:39.107 に答える