c++stdvectorc++17stdstringvisual-c++-2017

Difference in methods for converting std string to char*


I know there are a ton questions on how to convert a std::string to a char* and through my research, I have adopted a few different options. However, the only one that seems to work for me is const_cast from the c_str() method.

So I am using that for now, but would like to know more information as to why the other methods do not work. What am I missing in my understanding as to why this isn't working as intended which seems to work for many others.

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

I know the pitfalls of using const_cast but it works for my situation at the moment. I simply take the string from the user, pass it to a C API and do nothing else with it (no worries of it being modified).

Here is a sample of the output https://i.sstatic.net/TaiC8.jpg

So what am I doing wrong and is there a better way to do this?


UPDATE Thanks to everyone for the extremely fast answers. It seems that my underlying confusion was the assumption of the null terminating character not being in the new buffer that I was assigning to the char* variable. Hence why my output was showing random characters after the string (that should have been my clue but it has been so long since I've done C/C++)

I also should have tagged this C++17 originally (since fixed) as that is what I am aiming for. I did not have that enabled in my console app in Visual Studio which made the solution by Passer By below work. That is the method I will use going forward.

Bottom line, changing my target to C++17 this works as expected

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

Solution

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

    this will create the following vector:

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

    Anything jumps at you from that? It should. It doesn't contain the null terminator character. Any attempt to use testVec2.data() as a C string will result in Undefined Behavior because of this.

    Although from C++11 std::string's underlying buffer has to contain the null terminator character, the begin - end range doesn't include it.