现代的做法是什么?像<cstring>
这样的标题已被弃用,某些编码样式禁止使用“类C”函数。我有三种做同样事情的方法。哪一个是现代C ++最惯用的?
1。使用迭代器并包含空终止符
{
std::string test{"hello, world!"};
char* output = new char[test.size() + 1];
std::copy(test.begin(), test.end(),
output);
output[test.size() + 1] = '\0';
std::cout << output;
delete output;
}
2. 使用包含空终结符的c_str()
{
std::string test{"hello, world!"};
char* output = new char[test.size() + 1];
std::copy(test.c_str(), test.c_str() + std::strlen(test.c_str()),
output);
std::cout << output;
delete output;
}
3。使用std::strcpy
{
std::string test{"hello, world!"};
char* output = new char[test.size() + 1];
std::strcpy(output, test.c_str());
std::cout << output;
delete output;
}
我不希望看起来像面试官那样说“你使用strcpy,你必须是C程序员”。
答案 0 :(得分:16)
获取连续缓冲区的 modern safe pre C ++ 17方法是std::vector
。
std::string test{"hello, world!"};
std::vector<char> output(test.c_str(), test.c_str()+test.size()+1);
// use output.data() here...
从C ++ 17开始,std::string
有一个非常量data()
重载。
std::string test{"hello, world!"};
char * p = test.data();
答案 1 :(得分:11)
正确的方法是首先不使用new[]
。请改用std::vector
:
std::string temp {"Some string"};
std::vector<char> data (begin(temp), end(temp));
// If '\0' termination is required:
data.push_back('\0');
您可以使用data
访问data.data()
的基础缓冲区。如果您担心由push_back
引起的重新分配,您可以std::vector::reserve
在分配范围之前留出足够的空间。
如果您不需要实际可修改的char
数组,则可以跳过该副本,并直接使用std::string::data
或std::string::c_str
返回的指针。
答案 2 :(得分:1)
虽然其他答案提供了很好的建议,而且几乎在所有情况下都是正确的做法,但在某些情况下,您可能会被迫使用char*
而不是容器。最常见的情况是,如果您需要直接与C代码接口,并且被调用的C方法需要非const
指针(即它将取得内存的所有权)。
我将如何进行转换:
#include <string>
#include <cstdlib>
char* convert(const std::string& source)
{
const auto result = (char*) std::malloc(source.length() + 1);
source.copy(result, source.length());
result[source.length()] = '\0';
return result;
}
然后你有类似的东西:
int main()
{
const std::string foo {"hello"};
auto p = convert(foo);
some_nasty_c_method(p); // promises to free p
// other stuff
}
根据经验,如果您需要自己delete
,请不要这样做;使用容器,或改为使用std::unique_ptr
。