我可以从C++;一串 C++中的正确性仍然让我头痛。在使用一些旧的C代码时,我发现自己需要将C C++字符串对象分配给C字符串并将其赋值给变量。但是,该变量是一个char*,c_str()返回一个const char[]。有没有一个好方法可以绕过这个问题,而不必使用我自己的函数来实现它

我可以从C++;一串 C++中的正确性仍然让我头痛。在使用一些旧的C代码时,我发现自己需要将C C++字符串对象分配给C字符串并将其赋值给变量。但是,该变量是一个char*,c_str()返回一个const char[]。有没有一个好方法可以绕过这个问题,而不必使用我自己的函数来实现它,c++,c,string,C++,C,String,编辑:我还试图避免打电话给new。我很乐意用稍微复杂一点的代码换取更少的内存泄漏。我想总有strcpy 在C++代码的部分中使用 char */COD>字符串,这些字符串必须与旧的东西连接。 < >或重构现有代码,用C++编译器编译,然后使用 STD:String > < P>可以使用的方法: > MySTR < /C> >是您的C++字符串和 CSTR < /COD> >代码> char */COD>至少有 MySTR.Langthh()/Cuth> + 1大小。另外,len类型为si

编辑:我还试图避免打电话给new。我很乐意用稍微复杂一点的代码换取更少的内存泄漏。

我想总有
strcpy

在C++代码的部分中使用<代码> char */COD>字符串,这些字符串必须与旧的东西连接。

< >或重构现有代码,用C++编译器编译,然后使用<代码> STD:String >

< P>可以使用的方法:


<> > <代码> MySTR < /C> >是您的C++字符串和<代码> CSTR < /COD> >代码> char */COD>至少有<代码> MySTR.Langthh()/Cuth> + 1大小。另外,
len
类型为
size\u t
,并且是必需的,因为复制不会以空终止
cStr

始终存在常量转换

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

当然,这基本上颠覆了类型系统,但有时在与旧代码集成时是必要的

如果您知道
std::string
不会更改,则C样式转换将起作用

std::string s("hello");
char *p = (char *)s.c_str();
当然,
p
指向由
std::string
管理的某个缓冲区。如果
std::string
超出范围或缓冲区被更改(即写入),
p
可能无效

如果重构代码是不可能的,那么最安全的做法是复制字符串。

如果
c\u str()
将字符串对象内部缓冲区的副本返回给您,您可以使用
const\u cast


但是,如果
c_str()
允许您直接访问字符串对象内部缓冲区,请创建一个显式副本,而不是删除常量。

您自己真的那么难吗

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

这里有一个重要的区别,你需要做的是:
char*
,你想赋予它“道德上的恒定性”吗?也就是说,丢弃
常量
-ness仅仅是一个技术性的问题,并且您仍然会将字符串视为
常量
?在这种情况下,您可以使用cast-C-style或C++-style
const\u cast
。只要您(以及维护此代码的任何其他人)具有将
char*
视为
const char*
的原则,您就不会有问题,但编译器将不再监视您,因此如果您将其视为非
const
,您可能正在修改代码中其他内容所依赖的缓冲区

如果您的
char*
将被视为非
const
,并且您打算修改它所指向的内容,那么您必须复制返回的字符串,而不是丢弃它的
const
-ness。

因为c_str()允许您直接常量访问数据结构,所以您可能不应该强制转换它。不必预先分配缓冲区的最简单方法就是使用strdup

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

快速、简便、正确。

如果您负担得起额外的分配,而不是推荐的<代码> 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()
//假设您有字符串:
std::string一些_字符串(“hello world”);
//您可以这样从它生成一个向量:
std::vector一些_缓冲区(一些_string.begin(),一些_string.end());
//假设您的C函数声明如下:
//一些c_函数(char*buffer);
//您可以像这样将此向量传递给它:
一些_c_函数(&一些_缓冲区[0]);
//如果该函数还需要缓冲区大小,
//给它一些缓冲

对我来说,这比C++代码更简单一些——StrucP。请看一下Meyers的有效STL第16项,以获得比我所能提供的更好的解释。

在C++1x中,这应该可以:

foo(&s[0], s.size());

但是这需要注意:只有在调用任何可能更改字符串的成员函数之前,
&s[0]
(作为
s.c_str()
,顺便说一句)的结果才能保证有效。因此,您不应将这些操作的结果存储在任何地方。最安全的方法是在完整表达式的末尾使用它们,就像我的示例所做的那样


C++-11之前的答案

由于我莫名其妙的原因,没有人像我现在这样回答这个问题,而且由于其他问题现在已经结束,指向这个问题,我将在这里补充这一点,即使来得太晚了一年,这将意味着它挂在最底部


对于C++03,
std::string
不能保证将其字符存储在连续的内存中,并且
C_str()
的结果不需要指向字符串的内部缓冲区,因此保证工作的唯一方法是:

std::vector<char> buffer(s.begin(), s.end());
foo(&buffer[0], buffer.size());
s.assign(buffer.begin(), buffer.end());
std::向量缓冲区(s.begin(),s.end());
foo(&buffer[0],buffer.size());
s、 赋值(buffer.begin(),buffer.end());
这在C++11中不再适用

std::string vString;
vString.resize(256); // allocate some space, up to you
char* vStringPtr(&vString.front());
// assign the value to the string (by using a function that copies the value).
// don't exceed vString.size() here!
// now make sure you erase the extra capacity after the first encountered \0.
vString.erase(std::find(vString.begin(), vString.end(), 0), vString.end());
// and here you have the C++ string with the proper value and bounds.
<> >强>这是如何将C++字符串转换成C字符串。但是确保您知道您正在做什么,因为使用原始字符串函数很容易走出界限。有时这是必要的。

只需使用
const_cast(str.data())

不要觉得不好或奇怪,这样做是非常好的风格

它保证在C++11中工作。事实上,它的const-qualified完全符合之前的原始标准,这可以说是一个错误;在C++03中,可以将
string
实现为一个不连续的内存列表,但从来没有人这样做过。地球上没有一个编译器实现
stringstd::vector<char> buffer(s.begin(), s.end());
foo(&buffer[0], buffer.size());
s.assign(buffer.begin(), buffer.end());
std::string vString;
vString.resize(256); // allocate some space, up to you
char* vStringPtr(&vString.front());
// assign the value to the string (by using a function that copies the value).
// don't exceed vString.size() here!
// now make sure you erase the extra capacity after the first encountered \0.
vString.erase(std::find(vString.begin(), vString.end(), 0), vString.end());
// and here you have the C++ string with the proper value and bounds.
launchGame((char *) string.c_str());