当我尝试编译以下函数时,我收到错误。
string& foo(){
return "Hello World";
}
Error:
1 IntelliSense: a reference of type "std::string &" (not const-qualified) cannot be initialized with a value of type "const char [12]"
答案 0 :(得分:21)
您的代码存在两个问题。首先,"Hello World!"
是一个
char const[13]
,而不是std::string
。所以编译器必须这样做
(隐式地)将其转换为std::string
。一个结果
转换是一个临时的(在C ++中的价值 - 说话),你不能
使用临时初始化对非const的引用。第二是
即使你可以(或你宣布该函数返回一个。)
引用const),你将返回对某些内容的引用
将立即超出范围(因此被破坏);任何使用
结果引用将导致未定义的行为。
真正的问题是:为什么参考?除非你真的
指的是具有更长寿命的物体中的某物
意图是客户端代码修改它(通常不是一个好主意,但是
你应该有明显的例外,例如矢量的operator[]
按价值回报。
答案 1 :(得分:10)
“Hello World”不是字符串,它是一个char数组。 c ++编译器需要将其转换为字符串值,而不是字符串引用(因为它不是字符串),因此您的函数应该如下所示:
string foo(){
return "Hello World";
}
要扩展(根据OP的请求),编译器会执行以下操作:
string foo(){
char a[] = "Hello World";
string s( a );
return s;
}
值s由std :: string复制构造函数复制出函数。
答案 2 :(得分:2)
您正在指示编译器返回从char数组“Hello World”创建的临时std :: string。它需要把它放在某个地方并让某人负责清理它。您可以通过以下几种方式实现这一目标:
第二个可能是最简单的。编译器将使用RVO(返回值优化)来删除由此调用的副本。
答案 3 :(得分:0)
就这样做。
const string foo() {
return string("Hello World");
}
答案 4 :(得分:-1)
我想你想要:
string foo(){
return "Hello World";
}
答案 5 :(得分:-1)
要了解问题及其解决方案,您必须了解编译器的一些工作。但是,别担心,我会解释并尽可能保持简单。
在第一个例子中,我们想返回一个“引用”到一个已经创建的字符串,它应该有一个内存地址(我的意思是一个左值)。如果我们返回,就像这样:
string& foo()
{
return "Example String";
}
它永远不会奏效,因为您可能已经找到了原因。字符串:“示例字符串”是一个临时值,没有内存地址,因为它还没有被构造。它必须在任何字符串变量内的某处构造,在那里它将被分配给一个内存地址。目前,它没有内存地址(我的意思是右值)。
类似地,在第二种情况下,如果我们这样做:
string foo()
{
return "Example String";
}
在这里,我们实际上是在构造一个新的 String 类型的变量,从它被调用的地方。例如,如果我们这样做:
int main()
{
string Test = foo();
}
将在相等运算符的右侧创建一个字符串变量,并将数据复制到测试变量(如果禁用编译器优化)。但是等等,还有别的东西。
这里有一些编译器的魔法?。不把事情复杂化:),我只想说,它也有 string& foo() 和 string foo() 的特性,还有一些额外的特性。
这意味着如果我们做这样的事情:
const string& foo()
{
string Test = "Example String";
return Test;
}
这将返回字符串 Test 的(常量)“引用”。这是很明显的。但是,如果我们这样做:
const string& foo()
{
return "Example String";
}
编译器将智能地为“示例字符串”创建一个临时寄存器(在汇编中)并将其存储在那里。然后,它会返回给您对该寄存器的引用。这个 Register 事情只发生在 const Reference 的情况下。
使用 const string& foo() 来解决您的问题,您可能知道我们这样做的原因:)。如果您想了解更多信息,请查看 C++ 中的类型系统的主题。快乐学习。