gpt4 book ai didi

c++ - 我的插槽类错过了 std::function 有什么?

转载 作者:搜寻专家 更新时间:2023-10-31 01:33:40 24 4
gpt4 key购买 nike

我写了自己的“插槽”又名“可调用包装器”,因为我想在其他对象上提供成员函数插槽重新绑定(bind)(即我需要一种方法来存储成员函数指针和指向相关类的指针)。

我运行了一个小型测试并发现我的系统(64 位 Linux)上的 std::function 是我的两倍(GCC/libstdc++)到三倍(Clang/libc++)自己实现了一个类似的类,大小为 16 字节。非成员函数和 lambda 的实现是这样的(const void* 第一个参数是为了与此处未显示的成员函数槽保持一致):

template<typename... ArgTypes>
class slot
{
public:
virtual ~slot() = default;

virtual void operator()(const void* object, ArgTypes...) const = 0;

protected:
slot() = default;
};

template<typename Callable, typename... ArgTypes>
class callable_slot : public slot<ArgTypes...>
{
public:
callable_slot(Callable function_pointer_or_lambda) : callable(function_pointer_or_lambda) {}

virtual void operator()(const void*, ArgTypes... args) const override { callable(args...); }

private:
Callable callable;
};

template<typename Callable>
class callable_slot<Callable> : public slot<>
{
public:
callable_slot(Callable function_pointer_or_lambda) : callable(function_pointer_or_lambda) {}

virtual void operator()(const void*) const override { callable(); }

private:
Callable callable;
};

template<typename Callable, typename... ArgTypes>
using function_slot = callable_slot<Callable, ArgTypes...>;

我知道像 target 这样的东西没有在这里实现,但我认为任何缺失的函数都不会增加对象的大小。

我要问的是:为什么 std::function 的大小比我上面的廉价实现大?

最佳答案

你的 function_slot需要 Callable和一组 args... , 并返回一个继承自 slot<args...> 的类型用virtual operator() .

要以多态方式将其用作值,您必须将其包装在智能指针中并将其存储在堆中,并且必须转发包装类 operator()slot<args...>一个。

std::function对应于那个包装器,而不是你的slotcallable_slot对象。

template<class...Args>
struct smart_slot {
template<class Callable> // add SFINAE tests here TODO! IMPORTANT!
smart_slot( Callable other ):
my_slot( std::make_unique<callable_slot<Callable, Args...>>( std::move(other) ) )
{}
void operator()( Args...args ) const {
return (*my_slot)(std::forward<Args>(args)...);
}
// etc
private:
std::unique_ptr<slot<Args...>> my_slot;
};

smart_slot更接近std::function比你的代码。至于std::function就此而言,您编写的所有内容都是 std::function 用户的实现细节永远不会看到。

现在,这只需要 std::function是一个指针的大小。 std::function更大,因为它具有所谓的小对象优化。

它不只是存储一个智能指针,它本身还有一 block 内存。如果您传入的对象适合该内存块,它会就地构造该内存块,而不是进行堆分配。

std::function对于简单的情况,例如传递函数指针,基本上是强制执行此操作的。质量实现适用于更大和更复杂的对象。 MSVC 对最大为两个 std::string 的对象执行此操作

这意味着如果你这样做:

std::function<void(std::ostream&)> hello_world =
[s = "hello world"s](std::ostream& os)
{
os << s;
};
hello_world(std::cout);

它不会对 std::function 的良好实现进行动态分配.

请注意,一些主要的图书馆供应商在这种情况下会进行动态分配。

关于c++ - 我的插槽类错过了 std::function 有什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41003983/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com