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

时间:2014-06-04 19:26:06

标签: c++ string

这不是我的程序,所以不要开始责备我:-)。我得到了一些随机程序。 MyFunc()返回一个全局声明的缓冲区。我使用VS2008并没有抱怨

static char buffer[1024];

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

但是当我添加这行代码时

char * ret;
ret = MyFunc() 

它抱怨:“错误:没有合适的转换函数从”std :: string“到”char *“存在”

我的问题是为什么编译器现在抱怨?为什么这种语法检查不稳定?再一次,我没有改变MyFunc()的自由。如果我可以在我的程序中

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

并摆脱语法错误,但真的想了解这种奇怪的行为。

3 个答案:

答案 0 :(得分:7)

string()有一个接受char *的构造函数,因此您可以获得自动转换。没有从字符串到char *的自动转换。你必须调用string :: c_str()来获取char *。

<强> 修改 虽然你只是要求解释这个行为,但是这个论坛中的其他人似乎认为我没有提到string :: c_str返回一个const char *,而不是一个简单的char *。但解释仍然存在:没有从字符串到char *或const char *的隐式/自动转换。如果它对您很重要,请随时阅读c_str here

答案 1 :(得分:3)

这不是语法,而是std::string的结构使编译器的行为不同。

当您从返回char*的函数返回std::string时,编译器会注意到std::string的构造函数需要char*,调用该构造函数,以及悄悄地返回结果。

当您尝试从std::string - 返回函数返回char*时,编译器会尝试查看是否有转换运算符从char*生成std::string },发现没有这样的运算符,并报告错误。

如果要将字符串转换为char*,则需要复制字符串的缓冲区,如下所示:

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

您可以认为单独返回c_str()是可以的,但是一个好主意:“备份”此C字符串的缓冲区属于{{1对象,所以一旦字符串被释放,访问缓冲区就会开始产生未定义的行为。这就是您在访问字符串缓冲区时需要制作显式副本的原因。当然,您还负责在复制的结果上调用std::string

答案 2 :(得分:1)

std::string被设计为可从char const*隐式构造,因为它支持使用字符串文字和典型的C样式代码字符串作为初始化值。

如果不支持这个,那么就必须使用一些中间函数,除了冗长和效率低下之外什么都不会增加。

然而,另一方面,std::string 故意设计为不会隐式转换为char const*。部分原因可能是 std::string在逻辑上是可变的,返回的原始指针只有在没有执行可能导致缓冲区替换或字符串破坏的操作时才有效。例如,

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

其中foo生成std::string,使s指向不再存在的缓冲区, 悬空指针 无效。

c_str()成员函数调用使转换成为可能。

如果一个人可以写出

,那么问题可能会更常见
    char const* s = foo();

并进行编译。


关于该删除(删除)文本,我意识到字符串在逻辑上是可变的还是不可变的完全无关紧要。抱歉。需要更多咖啡!