我有以下示例代码:
#include <functional>
#include <iostream>
#include <string>
void f(std::function<const std::string&()> fn) {
std::cout << "in f" << std::endl;
std::cout << "str: " << fn() << std::endl;
}
int main() {
std::string str = "a";
auto fn1 = [&]() { return str; };
auto fn2 = [&]() { const std::string& str2 = str; return str2; };
auto fn3 = [&]() -> const std::string& { return str; };
std::cout << "in main" << std::endl;
std::cout << "fn1: " << fn1() << std::endl;
std::cout << "fn2: " << fn2() << std::endl;
std::cout << "fn3: " << fn3() << std::endl;
f(fn1); // Segfaults
f(fn2); // Also segfaults
f(fn3); // Actually works
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我第一次写这篇文章时,我希望fn1()在内部调用f()将正确返回对strin 的引用main。鉴于这str是分配,直到f()返回后,这在我看来很好。但是实际上发生的是尝试访问fn1()内部段错误的返回f()。
发生相同的事情fn2(),但令人惊讶的是它fn3()可以正常工作。
由于fn3()工作和fn1()不,是有什么我缺少有关如何C ++演绎的拉姆达函数的返回值?那将如何创建此段错误?
作为记录,如果运行此代码,则为输出:
仅致电f(fn3):
in main
fn1: a
fn2: a
fn3: a
in f
str: a
Run Code Online (Sandbox Code Playgroud)
仅致电f(fn2):
in main
fn1: a
fn2: a
fn3: a
in f
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)
仅致电f(fn1):
in main
fn1: a
fn2: a
fn3: a
in f
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)
没有尾随返回类型的lambda,如下所示:
[&](){return str;};
Run Code Online (Sandbox Code Playgroud)
等效于:
[&]()->auto{return str;};
Run Code Online (Sandbox Code Playgroud)
因此,此lambda返回str的副本。
调用该std::function对象将得到以下等效代码:
const string& std_function_call_operator(){
// functor = [&]->auto{return str;};
return functor();
}
Run Code Online (Sandbox Code Playgroud)
调用此函数时,str将其复制到一个临时文件中,将引用绑定到该临时文件,然后销毁该临时文件。因此,您将获得著名的悬挂参考。这是一个非常经典的场景。
| 归档时间: |
|
| 查看次数: |
296 次 |
| 最近记录: |