Я могу вернуть струну до неконстанты от строки C++?

Правильность константы в C++ все еще дает мне головные боли. В работе с некоторым старым кодом C я должен для присвоения, превращают строковый объект C++ в струну до и присваивают его переменной. Однако переменная является a char * и c_str() возвраты a const char []. Существует ли хороший способ обойти это, не имея необходимость прокручивать мою собственную функцию, чтобы сделать это?

править: Я также стараюсь не называть новым. Я с удовольствием обменяю немного более сложный код на меньшее количество утечек памяти.

25
задан jergason 17 December 2009 в 05:42
поделиться

9 ответов

Я думаю, всегда есть strcpy .

Или используйте строки char * в частях вашего кода C ++, которые должны взаимодействовать со старым

Или реорганизуйте существующий код, чтобы скомпилировать его с помощью компилятора C ++, а затем использовать std: string .

12
ответ дан 28 November 2019 в 18:05
поделиться

Если вы можете позволить себе дополнительное выделение, вместо рекомендуемого strcpy я бы рассмотрел возможность использования std :: vector следующим образом:

// suppose you have your string:
std::string some_string("hello world");
// you can make a vector from it like this:
std::vector<char> some_buffer(some_string.begin(), some_string.end());
// suppose your C function is declared like this:
// some_c_function(char *buffer);
// you can just pass this vector to it like this:
some_c_function(&some_buffer[0]);
// if that function wants a buffer size as well,
// just give it some_buffer.size()

Для меня это немного больше похоже на C ++, чем на strcpy . Взгляните на «Эффективный элемент STL 16» Мейерса, чтобы получить гораздо более хорошее объяснение, чем я когда-либо мог дать.

5
ответ дан 28 November 2019 в 18:05
поделиться

Всегда есть const_cast ...

std::string s("hello world");
char *p = const_cast<char *>(s.c_str());

Конечно, это в основном подрывает систему типов, но иногда это необходимо при интеграции со старым кодом.

10
ответ дан 28 November 2019 в 18:05
поделиться

Вы можете использовать метод copy :

len = myStr.copy(cStr, myStr.length());
cStr[len] = '\0';

Где myStr - ваша строка C ++, а cStr a char * с размером не менее myStr.length () +1. Кроме того, len имеет тип size_t и необходим, потому что копия не завершается нулевым символом cStr .

5
ответ дан 28 November 2019 в 18:05
поделиться

Здесь необходимо сделать важное различие: является ли char * , которому вы хотите присвоить эту «моральную константу»? То есть отбрасывание const -ness просто формальность, и вы действительно все равно будете рассматривать строку как const ? В этом случае вы можете использовать приведение - в стиле C или C ++ const_cast . Пока у вас (и у всех, кто когда-либо поддерживает этот код) есть дисциплина рассматривать этот char * как const char * , все будет в порядке, но компилятор будет больше не следите за вашей спиной, поэтому, если вы когда-нибудь относитесь к нему как к не const , вы можете изменять буфер, на который полагается что-то еще в вашем коде.

12
ответ дан 28 November 2019 в 18:05
поделиться

Если вы знаете, что std :: string не изменится, приведение в стиле C.

std::string s("hello");
char *p = (char *)s.c_str();

Конечно, ] p указывает на некоторый буфер, управляемый std :: string . Если std :: string выходит за пределы области видимости или буфер изменяется (т. Е. Записывается в), p , вероятно, будет недействительным.

Самым безопасным вариантом будет для копирования строки, если о рефакторинге кода не может быть и речи.

2
ответ дан 28 November 2019 в 18:05
поделиться

Если c_str () возвращает вам копию внутреннего буфера строкового объекта, вы можете просто использовать const_cast <> .

Однако, если c_str () дает вам прямой доступ к внутреннему буферу строкового объекта, сделайте явную копию вместо удаления константы.

1
ответ дан 28 November 2019 в 18:05
поделиться

Поскольку c_str () дает вам прямой константный доступ к структуре данных, вам, вероятно, не следует приводить его. Самый простой способ сделать это без предварительного выделения буфера - просто использовать strdup.

char* tmpptr;
tmpptr = strdup(myStringVar.c_str();
oldfunction(tmpptr);
free tmpptr;

Это быстро, легко и правильно.

1
ответ дан 28 November 2019 в 18:05
поделиться

Неужели это так сложно сделать самому?

#include <string>
#include <cstring>

char *convert(std::string str)
{
    size_t len = str.length();
    char *buf = new char[len + 1];
    memcpy(buf, str.data(), len);
    buf[len] = '\0';
    return buf;
}

char *convert(std::string str, char *buf, size_t len)
{
    memcpy(buf, str.data(), len - 1);
    buf[len - 1] = '\0';
    return buf;
}

// A crazy template solution to avoid passing in the array length
// but loses the ability to pass in a dynamically allocated buffer
template <size_t len>
char *convert(std::string str, char (&buf)[len])
{
    memcpy(buf, str.data(), len - 1);
    buf[len - 1] = '\0';
    return buf;
}

Использование:

std::string str = "Hello";
// Use buffer we've allocated
char buf[10];
convert(str, buf);
// Use buffer allocated for us
char *buf = convert(str);
delete [] buf;
// Use dynamic buffer of known length
buf = new char[10];
convert(str, buf, 10);
delete [] buf;
-3
ответ дан 28 November 2019 в 18:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: