【问题标题】:Extra copy constructors when std::function is used使用 std::function 时的额外复制构造函数
【发布时间】:2011-12-20 14:18:18
【问题描述】:

在我的项目中,有两个组件:生产者和消费者。生产者负责处理一些信息并将结果提供给消费者。结果在函数对象的帮助下传递。

我正在使用一个函数来传递这些信息。您可以在下面的代码中看到它的外观。

#include <iostream>
#include <vector>
#include <functional>

using namespace std;

class Data {
    std::vector<int> vec;
public:
    Data()  { 
        cout << "Data()" << endl; 
    }

    Data(const Data& rr) : vec(rr.vec)  {
        cout << "Data(Data&)" << endl;
    }

    ~Data() {
        cout << "~Data()" << endl;
    }

    Data(Data&& rr) : vec(move(rr.vec)) {
        cout << "Data(Data&&)" << endl;
    }

    void get() {
    }
};

class Producer {
public:
    void process(function<void(Data)> f) {
        Data data; 
        f(move(data));
    }

    void process2(void(&pf)(Data))  {
        Data c; 
        pf(move(c));
    }

};

void Consume(Data a) {
    cout << "Consume(data)" << endl;
}

int main() {
    {
        cout << "use function() " << endl;
        Producer p;
        p.process([](Data a) {
            cout << "Consume(data)" << endl;
        });
    }

    {
        cout << endl;
        cout << "use function pointer" << endl;
        Producer p;;
        p.process2(Consume);
    }
    return 0;
}

它有以下输出

    use function() 
    Data()
    Data(Data&&)
    Data(Data&)
    Data(Data&)
    Consume(data)
    ~Data()
    ~Data()
    ~Data()
    ~Data()

    use function pointer
    Data()
    Data(Data&&)
    Consume(data)
    ~Data()
    ~Data()

使用函数对象时还有额外的复制构造函数。

我做错了吗?是否有可能摆脱这些额外的构造函数?

提前谢谢你。

我正在使用 VC10 SP1。

【问题讨论】:

  • 使用 g++ 它只调用移动构造函数 3 次。
  • std::function 又大又贵...希望您有良好的编译器优化,但是考虑到std::function 为您提供的巨大灵活性,可以优化的程度是有限的。在紧要关头,当性能很重要时,首选函数指针或auto/lambda,而不是显式转换为std::function
  • 将在 MSVC11 中修复。在这里查看我的答案:stackoverflow.com/questions/8203211/…
  • 您的生产代码是否使用完全相同的执行流程?
  • @refp,类似,但不是。我试图在函数参数中用T 替换const T&amp;,但它没有我预期的那么有效。

标签: c++ visual-c++ c++11 function-pointers


【解决方案1】:

这里有几个选项。

  • 不要使用std::function,您的非捕获 lambda 可以转换为 void(*)(Data)
  • 不要使用std::function,制作你的函数模板,编译器可以推断出lambda的隐藏类型。
  • 不要复制对象,将它们作为指针或引用传递。根据程序的完整版本所做的事情,在堆上分配并使用std::unique_ptr 可能更有效。

【讨论】:

    猜你喜欢
    • 2013-05-27
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多