如何在 std 函数 lambda c++ 11 中正确捕获参数包

Sam*_*uel 2 c++ lambda c++11 std-function parameter-pack

我一直在尝试捕获 std 函数 lambda 中的一些参数包参数,以便将函数保存在内存中以供将来使用。

然而,在某些情况下,如果这些捕获的参数中的任何值在捕获后被修改,则这些参数的未来使用不会达到预期的效果。

我想在我的 std 函数中存储参数包的不可变副本。

该代码将作为库实现,因此用户可以使用它来保存一些文本以供将来打印。这样我们就无法管理参数包中收到的参数。此示例必须对字符串、const char *、int、float 有效...

这是示例代码:代码链接

template <typename... Args>
void doPrint(std::ostream& out, const Args &... args)
{
    using expander = int[];
    (void)expander{0, (void(out << args), 0)...};
}

template<typename... Args>
void printArgs(const Args & ... args)
{
    doPrint(std::cout, args...);
}

class PrintTest
{
private:

    std::vector<std::function<void()>> myFunctions;   

public:

    template<typename... Args>
    void saveText(const char * text, const Args & ... args)
    {
        std::function<void()> f = [this, text, args...]()
        {
            std::cout << text;
            printArgs(args ...);
            std::cout << std::endl;
        };

        this->myFunctions.push_back(f);
    }

    void printSavedTexts()
    {
        for(auto fun : this->myFunctions)
            fun();

        this->myFunctions.clear();
    }

};

int main()
{
    PrintTest test;

    {
        int four = 4;
        test.saveText(" Hello world ", 1, 2, 3, std::to_string(four).c_str());

        std::string a ="Just";
        const char * b = " be ";
        test.saveText(" Bye, Bye! ", a.c_str(), b, std::string("yourself!").c_str());
        a = "?";

        for(int i = 0; i <= 5; ++i)
        {
            std::string n = std::to_string(i);
            test.saveText("", n.c_str());
        }
    }

   test.printSavedTexts();
}
Run Code Online (Sandbox Code Playgroud)

这个例子的输出是:

// Hello world 1234
// Bye, Bye! ? be yourself!
// 5
// 5
// 5
// 5
// 5
// 5
Run Code Online (Sandbox Code Playgroud)

它应该是:

// Hello world 1234
// Bye, Bye! Just be yourself!
// 0
// 1
// 2
// 3
// 4
// 5
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法将收到的文本和参数包保存在内存中以供将来使用?而不是使用存储在向量中的 std 函数。

son*_*yao 5

在 中test.saveText("", n.c_str());,您传递了一个从toconst char*获得的指针,该指针最后由 lambda 捕获。当退出循环时被销毁,使捕获的指针悬空。对他们的尊重导致了 UB。nsaveTextnfor

您可以std::string直接使用,例如test.saveText("", n);;即删除所有的.c_str()s。

居住

  • @Samuel那么你必须小心原始指针;确保它们在 lambda 中使用时仍然有效。 (2认同)