You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何以std::function形式调用operator()无法正常工作?

问题分析:std::function包装issues_t后无法修改原对象的原因

我写了一个用来收集字符串序列的小型类:

class issues_t final
{
 private:
    std::vector<std::string> m_issues;

 public:
    constexpr void operator()(std::string&& txt)
       {
        m_issues.push_back( std::move(txt) );
       }
};

我计划这样使用它:

issues_t issues;
do_something(issues);

下面这种写法能正常工作:

void do_something(issues_t& notify_issue)
{
    notify_issue("something");
}

但我更想用下面这种方式:

using fnotify_t = std::function<void(std::string&&)>;
void do_something(fnotify_t const& notify_issue)
{
    notify_issue("something");
}

这种写法能编译通过,但实际运行时,虽然push_back()执行了,底层的vector却没有被填充。最小可复现示例如下:

#include <string>
#include <vector>
#include <functional>
#include <print>

class issues_t final
{
 private:
    std::vector<std::string> m_issues;

 public:
    constexpr void operator()(std::string&& txt)
       {
        m_issues.push_back( std::move(txt) );
       }

    [[nodiscard]] constexpr auto begin() const noexcept { return m_issues.cbegin(); }
    [[nodiscard]] constexpr auto end() const noexcept { return m_issues.cend(); }
};

using fnotify_t = std::function<void(std::string&&)>;
void do_first(fnotify_t const& notify_issue)
{
    notify_issue("do_first");
}

void do_second(issues_t& notify_issue)
{
    notify_issue("do_second");
}

int main()
{
    issues_t issues;
    issues("main");
    do_first(issues);
    do_second(issues);

    for( const auto& issue : issues )
       {
        std::print("    {}\n", issue);
       }
}

问题原因

当你把issues_t对象直接传给std::function时,std::function会拷贝一份原对象,而不是存储原对象的引用。后续调用notify_issue("do_first")时,实际操作的是std::function内部的那份拷贝,原issues对象完全没被修改,所以你看不到"do_first"被添加进去。

解决方案

要让std::function操作原对象,你需要存储原对象的引用,最简洁的方式是用std::ref包装原对象:

修改main中的调用:

do_first(std::ref(issues));

这样std::function会存储原对象的引用,后续调用时就会直接操作原issues对象。

验证结果

修改后的main函数运行后,输出会包含:

main
    do_first
    do_second

完全符合预期。

内容的提问来源于stack exchange,提问作者MatG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:14:57