Разница в методах преобразования строки std в char *

Я знаю, что существует множество вопросов о том, как преобразовать std :: string в char *, и благодаря моим исследованиям я принял несколько разных вариантов. Тем не менее, единственное, что мне подходит, это const_cast из метода c_str ().

Поэтому я использую это сейчас, но хотел бы узнать больше информации о том, почему другие методы не работают. Чего мне не хватает в моем понимании того, почему это не работает, как задумано, что, кажется, работает для многих других.

#include "stdafx.h"#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
char* test = "Hello World";
string testStr(test);

vector<char> testVec2(testStr.begin(), testStr.end());
// testVec2[0] = 'F';
char* test2 = reinterpret_cast<char*>(testVec2.data());

vector<char> testVec3(testStr.begin(), testStr.end());
// testVec3[0] = 'G';
char* test3 = &testVec3[0];

// The only one that works
char* test4 = const_cast<char*>(testStr.c_str());

cout << "char* test: " << test << " [" << strlen(test) << "]" << endl;
cout << "str test: " << testStr << " [" << testStr.length() << "]" <<     endl;
cout << "=== conv testing === " << endl;
cout << "char* test2: " << test2 << " [" << strlen(test2) << "]" <<     endl;
cout << "char* test3: " << test3 << " [" << strlen(test3) << "]" << endl;
cout << "char* test4: " << test4 << " [" << strlen(test4) << "]" << endl;

cin.get();
return 0;
}

Я знаю подводные камни использования const_cast, но в данный момент это работает для моей ситуации. Я просто беру строку у пользователя, передаю ее в C API и больше ничего с ней не делаю (не стоит беспокоиться об ее изменении).

Вот пример вывода
https://imgur.com/a/2S1HD

Так что я делаю не так и есть ли лучший способ сделать это?


ОБНОВИТЬ
Спасибо всем за чрезвычайно быстрые ответы. Кажется, что в основе моей путаницы было предположение, что нулевой завершающий символ не находится в новом буфере, который я назначил переменной char *. Следовательно, почему мой вывод показывал случайные символы после строки (это должно было быть моей подсказкой, но это было так давно, так как я делал C / C ++)

Я также должен был пометить этот C ++ 17 изначально (после исправления), потому что это то, к чему я стремлюсь. Я не включил это в своем консольном приложении в Visual Studio, что сделало решение Passer By ниже работающим. Это метод, который я буду использовать в дальнейшем.

Итог, меняя цель на C ++ 17, это работает как положено

char* test = "Hello World";
string testStr(test);
vector<char> testVec2(testStr.begin(), testStr.end());
char* test2 = testStr.data();

-1

Решение

vector<char> testVec2(testStr.begin(), testStr.end());

это создаст следующий вектор:

vector<char> testVec2 = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};

Что-то прыгает на тебя от этого? Должно. Он не содержит нулевой символ-терминатор. Любая попытка использовать testVec2.data() из-за этого строка C приведет к неопределенному поведению.

Хотя из C++11 std::stringБазовый буфер должен содержать нулевой символ-терминатор, begin - end Диапазон не включает это.

4

Другие решения

В C ++ 17 самый простой способ получить char* из std::string это просто

std::string str = "Why is this only available since C++17?";
some_c_function(str.data());

Относительно того, почему другие методы не работают, обратитесь к ответ Болова

3

поскольку c++11 лучший способ получить неконстантная char* из std::string это использовать это:

std::string s = "hello";

my_non_const_correct_c_function(&s[0]); // better than using const_cast

С const_cast вы можете столкнуться с неопределенное поведение если вы используете его на std::string это не было объявлено const,

1
По вопросам рекламы [email protected]