了解C++中函数的值类别

Understanding value category of functions in C++

本文关键字:函数 C++ 了解      更新时间:2023-10-16

首先,我已经通读了这篇文章,解释了std::movestd::forward的功能。在那篇文章中,有一个示例代码片段,如下所示,我在测试中使用了它。

std::map<std::string, std::function<void()>> commands;
template<typename ftor>
void install_command(std::string name, ftor && handler)
{
  commands.insert({
    std::move(name),
    std::forward<ftor>(handler)
  });
}

由于我想尝试实际用法,我编写了一段简单的代码,如下所示。

#include <iostream>
#include <map>
#include <functional>
using namespace std;
// code copied from above goes here
void fnA() { cout << "Function A." << endl; }
function<void()> fnB = [&]() -> void {
    cout << "Function B." << endl;
}
void RunTest() {
    install_command("#1", fnA);
    install_command("#2", move(fnA));
    install_command("#3", fnB);
    //install_command("#4", move(fnB));
    fnA();
    fnB();
    for (const auto& p : commands) {
        cout << p.first.c_str() << ": " << &p.second << endl;
    }
}
int main() {
    RunTest();
    return 0;
}

程序用-std=c++11编译,执行结果如下。

Function A.
Function B.
#1: 0xaf8088
#2: 0xaf8018
#3: 0xaf81a8

如果我取消注释该行install_command("#4", move(fnB));,则会出现运行时错误。

terminate called after throwing an instance of 'std::bad_function_call'
  what():  bad_function_call
Function A.

我相信 lambda 函数的所有权已从 function<void()> fnB 转移到 commands["#4"] ,但为什么fnA()工作而fnB()不起作用?

fnA是一个常规函数,而不是std::function fnB

当你这样做时

commands.insert({
    std::move(name),
    std::forward<ftor>(handler)
})

您创建

  • std::function<void()>void(&)() fnA
  • std::function<void()>void(&)() std::move(fnA)
  • std::function<void()>& std::function<void()>用于fnB(因此复制构造函数(
  • std::function<void()>std::function<void()>&& std::move(fnB)(因此移动构造函数(

只有后面修改输入参数。