【问题标题】:Unlike STL and std::basic_string, why there is no default allocator for std::function与 STL 和 std::basic_string 不同,为什么 std::function 没有默认分配器
【发布时间】:2021-04-03 07:23:06
【问题描述】:

与 STL 和 std::basic_string 不同,std::function 没有默认分配器。为什么?

C++11 中没有std::function 的默认分配器。 但是这篇文章(https://docs.microsoft.com/en-us/cpp/standard-library/allocators?view=msvc-160)持相反的观点,它说:

在 C++11 中,所有采用分配器类型参数的标准库类型和函数都支持最小分配器接口,包括 std::functionshared_ptrallocate_shared()basic_string

template< class Alloc >
function( std::allocator_arg_t, const Alloc& alloc,
              std::nullptr_t ) noexcept;

template<
    class CharT,
    class Traits = std::char_traits<CharT>,
    class Allocator = std::allocator<CharT>
> class basic_string;

template<class T,
class Allocator = std::allocator<T>
> class vector;

【问题讨论】:

  • 你问的构造函数不是在 C++17 中删除了吗?
  • 可能是因为这些函数的非分配器版本会使用“默认”分配器?那么指定它的唯一原因是覆盖默认值?
  • @JohnZwinck 所以,即使在 C++11 中,std::function 也没有默认分配器。但是这篇文章持有相反的观点,它说:“在 C++11 中,所有标准库采用分配器类型参数的类型和函数支持最小分配器接口,包括 std::function、shared_ptr、allocate_shared() 和 basic_string。"
  • 那你的问题是什么?我们不知道微软为什么这么写。
  • @JohnZwinck Miscrosoft 说std::function 有一个默认分配器,但据我所知,没有。

标签: c++ c++11 stl std-function allocator


【解决方案1】:

在C++11及以后,最常用的非默认构造函数是这个:

template<class F> function(F);

我将忽略其他讨论,因为它们不太有趣,但同样的信息适用于他们。

在 C++11 和 C++14 中也有这个,在 C++20 中被删除了:

template<class F, class Alloc> function(std::allocator_arg_t, const Alloc&, F);

你的问题是为什么它在 C++11 和 C++14 中没有 this 而不是上面的构造函数:

template<class F, class Alloc> function(F, const Alloc& = Alloc());

答案是没有办法使用默认参数调用这样的构造函数,因为function(f)总是调用第一个构造函数,而C++没有办法指定Alloc模板参数。有关 C++ 限制的更多信息,请参见此处:Can the template parameters of a constructor be explicitly specified?

许多其他类型(例如 std::vector)是不同的,因为它们的分配器模板参数位于整个类类型上,而不仅仅是在其构造函数上。

【讨论】:

    【解决方案2】:

    我假设您知道在 C++17 中删除了 std::function 中的分配器支持,所以我的回答将涵盖 C++11 和 C++14,caveat 表示:

    std::function 的分配器支持指定不佳且实施不一致。一些实现[没有]根本不提供重载(6-10),一些提供[d]重载但忽略[d]提供的分配器参数,一些提供[d]重载并使用[d]提供的分配器构造,但不是在 std::function [被] 重新分配时。

    在 C++11 和 C++14 中,std::function 没有分配器模板参数,因为它不是必需的。所有将调用分配器的成员也接受分配器作为函数(构造函数)模板参数;并且由于 std::function 对包装的可调用对象执行类型擦除,因此在分配器上执行类型擦除也很简单。

    在 Microsoft 文档中(我的重点):

    在 C++11 中,所有采用分配器类型参数的标准库类型和函数都支持最小分配器接口,包括std::function、[...]

    这是指std::function构造函数 采用分配器参数(在C++17 中已删除),它们是采用分配器的函数;在这种情况下,构造函数是一个函数。

    【讨论】:

    • 您看到std::vectorstd::basic_string 有默认分配器(即std::allocator)。但是std::function 没有默认分配器。为什么?
    • @John 因为不需要它;使用的分配器不会影响类型(因为它已被擦除)并且用户无需知道构造函数使用了哪个分配器而不采用allocator_arg_t
    猜你喜欢
    • 2021-04-07
    • 1970-01-01
    • 2019-11-16
    • 2015-05-23
    • 2010-12-12
    • 1970-01-01
    • 2015-07-18
    相关资源
    最近更新 更多