将 std 字符串转换为 char* 的方法差异
Difference in methods for converting std string to 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();
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
范围不包含它。
因为 c++11
从 std::string
得到 非常量 char*
的最好方法是使用这个:
std::string s = "hello";
my_non_const_correct_c_function(&s[0]); // better than using const_cast
使用 const_cast
如果你在未声明 [=16] 的 std::string
上使用它,你可以 运行 进入 未定义的行为 =].
在 C++17 中,从 std::string
获取 char*
的最简单方法就是
std::string str = "Why is this only available since C++17?";
some_c_function(str.data());
其他方法为什么不行,参考
我知道有很多关于如何将 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();
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
范围不包含它。
因为 c++11
从 std::string
得到 非常量 char*
的最好方法是使用这个:
std::string s = "hello";
my_non_const_correct_c_function(&s[0]); // better than using const_cast
使用 const_cast
如果你在未声明 [=16] 的 std::string
上使用它,你可以 运行 进入 未定义的行为 =].
在 C++17 中,从 std::string
获取 char*
的最简单方法就是
std::string str = "Why is this only available since C++17?";
some_c_function(str.data());
其他方法为什么不行,参考