简体   繁体   English

std :: string声明的函数不会抱怨返回char *

[英]std::string declared function does not complain returning char *

This is not my program so don't start berating me :-). 这不是我的程序,所以不要开始指责我:-)。 Some random program I got. 我得到了一些随机程序。 A globally declared buffer is being returned by MyFunc(). MyFunc()返回一个全局声明的缓冲区。 I use VS2008 and it does not complain 我使用VS2008,它不会抱怨

static char buffer[1024];

std::string MyFunc() {
    ....
    ....
    return buffer;
}

However when I add this line of code 但是,当我添加这一行代码时

char * ret;
ret = MyFunc() 

It complains: "error: no suitable conversion function from "std::string" to "char *" exists" 它抱怨:“错误:不存在从“ std :: string”到“ char *”的合适转换函数”

My question is why is the compiler complaining now? 我的问题是为什么编译器现在抱怨? Why this inconstancy in syntax checking? 为什么语法检查中存在这种不一致性? Again I dont have the freedom to change MyFunc(). 同样,我没有更改MyFunc()的自由。 In my program if I can make 在我的程序中,如果我可以

std::string ret;
ret = MyFunc(); 

and get rid of the syntax error but would really like to understand this strange behavior. 并摆脱语法错误,但真的很想了解这种奇怪的行为。

string() has a constructor that accepts a char*, so you get an automatic conversion. string()具有一个接受char *的构造函数,因此您可以进行自动转换。 There is no automatic conversion from a string to a char*. 没有从字符串到char *的自动转换。 You have to call string::c_str() to get the char*. 您必须调用string :: c_str()以获得char *。

Edit Although you asked only for an explanation of the behavior, others in this forum seem to think I have short-changed you by not mentioning that string::c_str returns a const char*, not a simple char*. 编辑尽管您只要求对行为进行解释,但该论坛中的其他人似乎认为我没有提到string :: c_str返回const char *,而不是简单的char *,从而对您有所作为。 But the explanation remains: there is no implicit/automatic conversion from string to char* or const char*. 但是解释仍然存在:没有从字符串到char *或const char *的隐式/自动转换。 Feel free to read about c_str here if it's important to you. 如果对您很重要,请随时在此处阅读有关c_str的信息

It is not the syntax, it is the structure of the std::string that makes the compiler behave differently. 不是语法,而是std::string的结构使编译器的行为有所不同。

When you are returning a char* from a function returning std::string , the compiler notices that there is a constructor of std::string that takes char* , calls that constructor, and quietly returns the result. 当您从返回std::string的函数中返回char* ,编译器会注意到有一个std::string构造函数,该构造函数采用char* ,并调用该构造函数并安静地返回结果。

When you are trying to return a std::string from a char* - returning function, the compiler tries to see if there is a conversion operator to make char* from a std::string , finds that there is no such operator, and reports an error. 当您尝试从char* -返回函数返回std::string ,编译器将尝试查看是否存在从std::string char*的转换运算符,发现没有这样的运算符,并且报告错误。

If you want to convert a string to char* , you need to make a copy of the string's buffer, like this: 如果要将字符串转换为char* ,则需要复制该字符串的缓冲区,如下所示:

char* ret_ch = new char[ret.size()+1];
memcpy(ret_ch, ret.c_str(), ret.size()+1);
return ret_ch;

You could think that it is OK to return c_str() by itself, but it is not a good idea: the buffer that "backs up" this C string belongs to std::string object, so once the string gets deallocated, accessing the buffer starts producing undefined behavior. 您可能认为可以c_str()返回c_str()很好,但这不是一个好主意:“备份”此C字符串的缓冲区属于std::string对象,因此一旦该字符串被释放,就访问缓冲区开始产生未定义的行为。 That is why you need to make an explicit copy when you access the buffer of a string. 这就是为什么在访问字符串缓冲区时需要进行显式复制的原因。 Of course you are also responsible for calling delete[] on the copied result. 当然,您还负责对复制的结果调用delete[]

std::string is designed as implicitly constructable from char const* because this supports using string literals and typical C style code strings as initializer values. std::string被设计为可从char const*隐式构造,因为它支持使用字符串文字和典型的C样式代码字符串作为初始值。

If this was not supported then one would just have to use some intermediate function, which would add nothing but verbosity and inefficiency. 如果不支持此功能,则仅需使用一些中间功能,除了冗长和效率低下外,什么都不会添加。

In the other direction, however, std::string is intentionally designed to not convert implicitly to char const* . 但是,从另一个方向来看, std::string 故意设计为不隐式转换为char const* Part of the rationale is probably that 部分原因可能是 with std::string being logically mutable, std::string在逻辑上是可变的, the returned raw pointer is only valid as long as no operations are performed that might cause a buffer replacement or string destruction. 返回的原始指针仅在不执行可能导致缓冲区替换或字符串破坏的操作的情况下才有效。 For example, 例如,

    char const* s = foo().c_str();

where foo produces a std::string , makes s point to a buffer that no longer exists, a dangling pointer that is invalid. 其中foo产生std::string ,使s指向一个不再存在的缓冲区,该指针是无效的。

The c_str() member function call makes the conversion stand out. c_str()成员函数调用使转换脱颖而出。

Consider how more common that problem could be if one could write just 考虑一下,如果一个人只能写一个问题,这个问题可能会更加普遍

    char const* s = foo();

and have that compile. 并进行编译。


Regarding that strike-through (deleted) text, I realized that it's completely irrelevant whether the string is logically mutable or immutable. 关于删除线文本,我意识到字符串在逻辑上是可变的还是不可变的完全无关紧要。 Sorry. 抱歉。 Need more coffee! 需要更多咖啡!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM