Does the address of the result of std::string::ope

2019-07-19 17:43发布

问题:

I am modifying a function that accepts a const char* and uses a function, ProcessString. ProcessString is a function that expects a null-terminated character buffer as a char*. The characters in the buffer may or may not be modified, as defined by the function signature below. To "bridge the gap", I am using a temporary std::string:

void ProcessString( char* str );

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

My primary question is about the guarantees of std::string::operator[] and whether the address returned by the &temp[0] above is a usable, null-terminated buffer as a char*. Secondly, and very much secondly, is there a better way to do this?

I am using C++03.

回答1:

That only has well-defined behavior in C++11; in previous standards, std::string did not guarantee contiguous storage for its internal buffer.

However while that code is completely fine in C++11, the more idiomatic approach is to use std:vector<char>, which has guaranteed contiguous storage since 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
}


回答2:

I have created a small class to face this kind of problem, I have implemented the RAII idiom.

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

And you can use it as:

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

I have called the class DeepString because it is creating a deep and unique copy (the DeepString is not copyable) of an existing string.



回答3:

If you need to go from a const char* to a char *, why not use strdup, and then free the buffer when ProcessString is done?

Going through std::string seems unnecessary to me.