У меня есть функция в библиотеке, которая принимает char* и изменяет данные.
Я попытался дать ему c_str(), но С++ docs говорят, что он возвращает const char*.
Что я могу сделать, кроме как создать массив char и скопировать его в это?
У меня есть функция в библиотеке, которая принимает char* и изменяет данные.
Я попытался дать ему c_str(), но С++ docs говорят, что он возвращает const char*.
Что я могу сделать, кроме как создать массив char и скопировать его в это?
Ничего.
Поскольку std::string управляет собой своим содержимым, вы не можете иметь доступ на запись к строковым данным. Это поведение undefined.
Однако создание и копирование массива char не сложно:
std::string original("text");
std::vector<char> char_array(original.begin(), original.end());
char_array.push_back(0);
some_function(&char_array[0]);
Вы можете использовать &str[0] или &*str.begin(), если:
resize();str.size() в качестве аргумента для размера буфера);\0, иначе str.size() вернет "предварительно выделенный размер" вместо "логического" размера строки.  Примечание: это гарантировано работает на С++ 11 (где строки гарантированно будут смежными), но не в предыдущих версиях стандарта; тем не менее, реализация стандартной библиотеки, которую я знаю, никогда не выполняла std::basic_string с несмежным хранилищем.
Тем не менее, если вы хотите пойти в безопасное место, используйте std::vector<char> (гарантированный соприкосновение с С++ 03); инициализируйте все, что захотите (вы можете скопировать свои данные из строки, используя конструктор, который принимает два итератора, добавив в конце нулевой символ), измените его размер так же, как вы бы сделали с std::string, и скопируйте его обратно в строку, останавливающуюся на первый символ \0.
Если вы знаете, что функция не будет изменяться за пределами str.size(), вы можете получить указатель одним из следующих способов:
void f( char* p, size_t s ); // update s characters in p
int main() {
   std::string s=...;
   f( &s[0], s.size() );
   f( &s.front(), s.size() );
}
Обратите внимание, что это гарантировано в С++ 11, но не в предыдущих версиях стандарта, где он допускал реализацию канатов (т.е. несмежную память)
Если ваша реализация не будет пытаться увеличить длину строки, то:
С++ 11:
std::string data = "This is my string.";
func(&*data.begin());
С++ 03:
 std::string data = "This is my string.";
 std::vector<char> arr(data.begin(), data.end());
 func(&arr[0]);
Здесь класс, который будет генерировать временный буфер и автоматически скопировать его в строку при ее уничтожении.
class StringBuffer
{
public:
    StringBuffer(std::string & str) : m_str(str)
    {
        m_buffer.push_back(0);
    }
    ~StringBuffer()
    {
        m_str = &m_buffer[0];
    }
    char * Size(int maxlength)
    {
        m_buffer.resize(maxlength + 1, 0);
        return &m_buffer[0];
    }
private:
    std::string & m_str;
    std::vector<char> m_buffer;
};
И вот как вы его используете:
// this is from a crusty old API that can't be changed
void GetString(char * str, int maxlength);
std::string mystring;
GetString(StringBuffer(mystring).Size(MAXLEN), MAXLEN);
Если вы думаете, что видели этот код раньше, это потому, что я скопировал его из вопроса, который я написал: Гарантированное время жизни временного в С++?