返回常量引用
Returning const reference
我对返回 const
对临时对象的引用的函数声明有些困惑。
在下面的代码中
#include <string>
#include <iostream>
using namespace std;
const string& foo() {
return string("foo");
}
string bar() {
return string("bar");
}
int main() {
const string& f = foo();
const string& b = bar();
cout << b;
}
方法 foo
和 bar
有什么区别?
为什么foo
给我warning: returning reference to local temporary object [-Wreturn-stack-address]
。不是在 const string& f = foo();
上创建的临时副本吗?
在这两种情况下,都会初始化一个字符串对象并将其分配到堆栈上。
return从函数中退出后,包含它的内存段变得无关紧要,其内容可能会被覆盖。
功能的区别:
bar
函数 return 在其中创建的字符串实例的副本。
foo
函数 returns 是对在其中创建的字符串实例的引用。
换句话说,它 return 是指向其 return 值的隐式指针,该值驻留在临时内存段中 - 这就是您发出警告的原因。
string("foo")
在函数本地创建一个类型为 std::string
的对象,其中包含值 "foo"
。该对象将在函数结束时被销毁。因此,一旦代码离开该函数 [1],返回对该对象的引用将无效。所以在 main
中,你永远不会有对该字符串的有效引用。如果您在 foo
.
中创建了一个局部变量,情况也是如此
返回引用的全部意义在于您不创建副本,并且初始化引用(string &f = foo()
是初始化)不会创建原始对象的副本 - 只是另一个引用相同的对象[在代码返回 main
时已经无效]。对于很多事情,引用可以看作是"a different name for the same thing"。
引用对象(换句话说,"alias name" 引用的实际对象)的生命周期应始终比引用变量(在本例中为 f
)的生命周期长。
在 bar
的情况下,代码将创建一个副本作为 return string("bar");
的一部分,因为您返回该对象而不获取其引用 - 换句话说,通过复制对象, 这样就可以了。
[1] 迂腐地,虽然仍在函数内部,但是在您在函数内部编写的代码结束后,编译器引入了一段代码来处理函数中创建的对象的销毁。
Isn't a copy of the temporary created on const string& f = foo();
你从哪里听到的?
将 const
添加到引用通常允许将用于初始化它的临时文件的生命周期延长到引用本身的生命周期。从来没有副本。
尽管如此,这里的情况并非如此。您绑定到引用的对象在函数末尾超出范围,并且优先于其他所有对象。
您正在返回悬空引用;期间。
Why does foo give me warning: returning reference to local temporary
object [-Wreturn-stack-address].
您正在 foo()
中创建一个临时字符串对象,并且您正在返回对该对象的引用,该对象将立即超出范围(悬挂引用)。
const string& foo() {
return string("foo"); // returns constant reference to temporary object
} // object goes out of scope
bar()
完全不同:
string bar() {
return string("bar"); // returns a copy of temporary string
}
...
const string& b = bar(); // reference an rvalue string
What is the difference between methods foo and bar ?
foo()
returns 常量(悬挂)引用,而 bar()
returns 临时字符串对象的副本。
我对返回 const
对临时对象的引用的函数声明有些困惑。
在下面的代码中
#include <string>
#include <iostream>
using namespace std;
const string& foo() {
return string("foo");
}
string bar() {
return string("bar");
}
int main() {
const string& f = foo();
const string& b = bar();
cout << b;
}
方法 foo
和 bar
有什么区别?
为什么foo
给我warning: returning reference to local temporary object [-Wreturn-stack-address]
。不是在 const string& f = foo();
上创建的临时副本吗?
在这两种情况下,都会初始化一个字符串对象并将其分配到堆栈上。 return从函数中退出后,包含它的内存段变得无关紧要,其内容可能会被覆盖。
功能的区别:
bar
函数 return 在其中创建的字符串实例的副本。
foo
函数 returns 是对在其中创建的字符串实例的引用。
换句话说,它 return 是指向其 return 值的隐式指针,该值驻留在临时内存段中 - 这就是您发出警告的原因。
string("foo")
在函数本地创建一个类型为 std::string
的对象,其中包含值 "foo"
。该对象将在函数结束时被销毁。因此,一旦代码离开该函数 [1],返回对该对象的引用将无效。所以在 main
中,你永远不会有对该字符串的有效引用。如果您在 foo
.
返回引用的全部意义在于您不创建副本,并且初始化引用(string &f = foo()
是初始化)不会创建原始对象的副本 - 只是另一个引用相同的对象[在代码返回 main
时已经无效]。对于很多事情,引用可以看作是"a different name for the same thing"。
引用对象(换句话说,"alias name" 引用的实际对象)的生命周期应始终比引用变量(在本例中为 f
)的生命周期长。
在 bar
的情况下,代码将创建一个副本作为 return string("bar");
的一部分,因为您返回该对象而不获取其引用 - 换句话说,通过复制对象, 这样就可以了。
[1] 迂腐地,虽然仍在函数内部,但是在您在函数内部编写的代码结束后,编译器引入了一段代码来处理函数中创建的对象的销毁。
Isn't a copy of the temporary created on
const string& f = foo();
你从哪里听到的?
将 const
添加到引用通常允许将用于初始化它的临时文件的生命周期延长到引用本身的生命周期。从来没有副本。
尽管如此,这里的情况并非如此。您绑定到引用的对象在函数末尾超出范围,并且优先于其他所有对象。
您正在返回悬空引用;期间。
Why does foo give me warning: returning reference to local temporary object [-Wreturn-stack-address].
您正在 foo()
中创建一个临时字符串对象,并且您正在返回对该对象的引用,该对象将立即超出范围(悬挂引用)。
const string& foo() {
return string("foo"); // returns constant reference to temporary object
} // object goes out of scope
bar()
完全不同:
string bar() {
return string("bar"); // returns a copy of temporary string
}
...
const string& b = bar(); // reference an rvalue string
What is the difference between methods foo and bar ?
foo()
returns 常量(悬挂)引用,而 bar()
returns 临时字符串对象的副本。