我可以从 C++ 字符串中取回非常量 C 字符串吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1919626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:35:34  来源:igfitidea点击:

Can I get a non-const C string back from a C++ string?

c++cstring

提问by jergason

Const-correctness in C++ is still giving me headaches. In working with some old C code, I find myself needing to assign turn a C++ string object into a C string and assign it to a variable. However, the variable is a char *and c_str()returns a const char []. Is there a good way to get around this without having to roll my own function to do it?

C++ 中的常量正确性仍然让我头疼。在使用一些旧的 C 代码时,我发现自己需要将一个 C++ 字符串对象赋值为一个 C 字符串并将其分配给一个变量。但是,变量是 achar *c_str()返回 a const char []。有没有一种好方法可以解决这个问题,而不必推出我自己的功能来做到这一点?

edit:I am also trying to avoid calling new. I will gladly trade slightly more complicated code for less memory leaks.

编辑:我也试图避免调用新的。我很乐意用稍微复杂的代码来减少内存泄漏。

采纳答案by dmckee --- ex-moderator kitten

I guess there is always strcpy.

我想总是有的strcpy

Or use char*strings in the parts of your C++ code that must interface with the old stuff.

或者char*在必须与旧内容交互的 C++ 代码部分中使用字符串。

Or refactor the existing code to compile with the C++ compiler and then to use std:string.

或者重构现有代码以使用 C++ 编译器进行编译,然后使用std:string.

回答by sbi

Since for to me inexplicable reasons nobody answered this the way I do now, and since other questions are now being closed pointing to this one, I'll add this here, even though coming a year too late will mean that it hangs at the very bottom of the pile...

由于对我来说莫名其妙的原因没有人像我现在这样回答这个问题,并且由于其他问题现在正在关闭指向这个问题,我会在这里添加这个,即使来得太晚意味着它会挂在最堆的底部...



With C++03, std::stringisn't guaranteed to store its characters in a contiguous piece of memory, and the result of c_str()doesn't need to point to the string's internal buffer, so the only way guaranteed to work is this:

使用 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());

Since there were no known implementations that actually used non-contiguous memory, and since std::stringwas used by many as if this was guaranteed, the rules will be changed for the upcoming standard, now guaranteeing contiguous memory for its characters. So in C++1x, this should work:

由于没有实际使用非连续内存的已知实现,并且由于std::string许多人都使用了这一点,就好像这是有保证的一样,规则将针对即将到来的标准进行更改,现在保证其字符的连续内存。所以在 C++1x 中,这应该有效:

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


Howeverthis needs a note of caution: The result of &s[0](as the result of s.c_str(), BTW) is only guaranteed to be valid until any member function is invoked that might change the string. So you should not store the resultof these operations anywhere. The safest is to be done with them at the end of the full expression, as my examples do.

但是,这需要注意&s[0]:(作为s.c_str(),BTW的结果)的结果仅保证在调用任何可能更改字符串的成员函数之前有效。所以你不应该在任何地方存储这些操作的结果。最安全的是在完整表达式的末尾使用它们,就像我的例子一样。

回答by Joe Mabel

There is an important distinction you need to make here: is the char*to which you wish to assign this "morally constant"? That is, is casting away const-ness just a technicality, and you really will still treat the string as a const? In that case, you can use a cast - either C-style or a C++-style const_cast. As long as you (and anyone else who ever maintains this code) have the discipline to treat that char*as a const char*, you'll be fine, but the compiler will no longer be watching your back, so if you ever treat it as a non-constyou may be modifying a buffer that something else in your code relies upon.

您需要在这里做出一个重要的区分:char*您希望将这个“道德常数”分配给哪个?也就是说,抛弃const-ness 只是一个技术问题,您真的仍会将字符串视为const? 在这种情况下,您可以使用强制转换 - C 样式或 C++ 样式const_cast。只要您(以及曾经维护此代码的任何其他人)有纪律地将其char*视为 a const char*,您就可以了,但编译器将不再监视您,因此如果您将其视为非 -const您可能正在修改代码中其他内容所依赖的缓冲区。

If your char*is going to be treated as non-const, and you intend to modify what it points to, you mustcopy the returned string, not cast away its const-ness.

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

回答by mch

There's always const_cast...

总是有 const_cast ...

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

Of course, that's basically subverting the type system, but sometimes it's necessary when integrating with older code.

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

回答by Dmitry

If you can afford extra allocation, instead of a recommended strcpyI would consider using std::vector<char>like this:

如果你能负担得起额外的分配,而不是推荐strcpy我会考虑使用std::vector<char>这样的:

// 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()

To me this is a bit more of a C++ way than strcpy. Take a look at Meyers' Effective STL Item 16 for a much nicer explanation than I could ever provide.

对我来说,这比strcpy. 看看 Meyers 的 Effective STL Item 16 以获得比我所能提供的更好的解释。

回答by Juan

You can use the copymethod:

您可以使用复制方法:

len = myStr.copy(cStr, myStr.length());
cStr[len] = '
std::string s("hello");
char *p = (char *)s.c_str();
';

Where myStris your C++ string and cStra char *with at least myStr.length()+1 size. Also, lenis of type size_tand is needed, because copy doesn't null-terminate cStr.

哪里myStr是你的C ++字符串和cStr一个char *至少myStr.length()+1大小。此外,len是 类型size_t并且是必需的,因为 copy 不会空终止cStr

回答by Anne Quinn

Just use const_cast<char*>(str.data())

只需使用 const_cast<char*>(str.data())

Do not feel bad or weird about it, it's perfectly good style to do this.

不要为此感到难过或奇怪,这样做是非常好的风格。

It's guaranteed to work in C++11. The fact that it's const qualified at all is arguably a mistake by the original standard before it; in C++03 it was possible to implement stringas a discontinuous list of memory, but no one ever did it. There is not a compiler on earth that implements stringas anything other than a contiguous block of memory, so feel free to treat it as such with complete confidence.

它保证在 C++11 中工作。它完全是 const 限定的这一事实可以说是它之前的原始标准的错误;在 C++03 中,可以实现string为不连续的内存列表,但从来没有人这样做过。string除了连续的内存块之外,地球上没有任何编译器可以实现,因此请放心地将其视为这样。

回答by Matt Davis

If you know that the std::stringis not going to change, a C-style cast will work.

如果您知道std::string不会改变,那么 C 风格的强制转换将起作用。

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

Of course, pis pointing to some buffer managed by the std::string. If the std::stringgoes out of scope or the buffer is changed (i.e., written to), pwill probably be invalid.

当然,p是指向一些由std::string. 如果std::string超出范围或缓冲区被更改(即写入),p则可能无效。

The safest thing to do would be to copy the string if refactoring the code is out of the question.

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

回答by Franci Penov

If c_str()is returning to you a copy of the string object internal buffer, you can just use const_cast<>.

如果c_str()返回给你一个字符串对象内部缓冲区的副本,你可以使用const_cast<>.

However, if c_str()is giving you direct access tot he string object internal buffer, make an explicit copy, instead of removing the const.

但是,如果c_str()让您直接访问字符串对象内部缓冲区,请进行显式复制,而不是删除常量。

回答by WarrenB

Since c_str() gives you direct const access to the data structure, you probably shouldn't cast it. The simplest way to do it without having to preallocate a buffer is to just use strdup.

由于 c_str() 为您提供了对数据结构的直接常量访问,您可能不应该强制转换它。无需预先分配缓冲区的最简单方法是使用 strdup。

##代码##

It's quick, easy, and correct.

它快速、简单且正确。