什么是空的`std::allocator`?即:`std::allocator<void>`。

10

自动生成的ROS(机器人操作系统)消息C ++头文件包含以下类型定义:

typedef  ::std_msgs::Header_<std::allocator<void> > Header;

这里的 std::allocator<void> 是什么意思?为什么模板类型是 void?它代表什么含义?在什么情况下使用?
这里是 std::allocator<> 的文档:
  1. https://www.cplusplus.com/reference/memory/allocator/
  2. https://en.cppreference.com/w/cpp/memory/allocator

以下是需要查看的自动生成示例文件:http://docs.ros.org/en/electric/api/std_msgs/html/msg__gen_2cpp_2include_2std__msgs_2Header_8h_source.html,第一行在第116行。
这是 ROS 自动生成的消息 Header_ 类的开头:
template <class ContainerAllocator>
struct Header_ {

下面是从自动生成的Header.h中提取出来的更多上下文,底部有各种typedef:

template <class ContainerAllocator>
struct Header_ {
  typedef Header_<ContainerAllocator> Type;

  Header_()
  : seq(0)
  , stamp()
  , frame_id()
  {
  }

  Header_(const ContainerAllocator& _alloc)
  : seq(0)
  , stamp()
  , frame_id(_alloc)
  {
  }

  typedef uint32_t _seq_type;
  uint32_t seq;

  typedef ros::Time _stamp_type;
  ros::Time stamp;

  typedef std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other >  _frame_id_type;
  std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other >  frame_id;


private:
  static const char* __s_getDataType_() { return "std_msgs/Header"; }
public:
  ROS_DEPRECATED static const std::string __s_getDataType() { return __s_getDataType_(); }

  ROS_DEPRECATED const std::string __getDataType() const { return __s_getDataType_(); }

private:
  static const char* __s_getMD5Sum_() { return "2176decaecbce78abc3b96ef049fabed"; }
public:
  ROS_DEPRECATED static const std::string __s_getMD5Sum() { return __s_getMD5Sum_(); }

  ROS_DEPRECATED const std::string __getMD5Sum() const { return __s_getMD5Sum_(); }

private:
  static const char* __s_getMessageDefinition_() { return "# Standard metadata for higher-level stamped data types.\n\
# This is generally used to communicate timestamped data \n\
# in a particular coordinate frame.\n\
# \n\
# sequence ID: consecutively increasing ID \n\
uint32 seq\n\
#Two-integer timestamp that is expressed as:\n\
# * stamp.secs: seconds (stamp_secs) since epoch\n\
# * stamp.nsecs: nanoseconds since stamp_secs\n\
# time-handling sugar is provided by the client library\n\
time stamp\n\
#Frame this data is associated with\n\
# 0: no frame\n\
# 1: global frame\n\
string frame_id\n\
\n\
"; }
public:
  ROS_DEPRECATED static const std::string __s_getMessageDefinition() { return __s_getMessageDefinition_(); }

  ROS_DEPRECATED const std::string __getMessageDefinition() const { return __s_getMessageDefinition_(); }

  ROS_DEPRECATED virtual uint8_t *serialize(uint8_t *write_ptr, uint32_t seq) const
  {
    ros::serialization::OStream stream(write_ptr, 1000000000);
    ros::serialization::serialize(stream, seq);
    ros::serialization::serialize(stream, stamp);
    ros::serialization::serialize(stream, frame_id);
    return stream.getData();
  }

  ROS_DEPRECATED virtual uint8_t *deserialize(uint8_t *read_ptr)
  {
    ros::serialization::IStream stream(read_ptr, 1000000000);
    ros::serialization::deserialize(stream, seq);
    ros::serialization::deserialize(stream, stamp);
    ros::serialization::deserialize(stream, frame_id);
    return stream.getData();
  }

  ROS_DEPRECATED virtual uint32_t serializationLength() const
  {
    uint32_t size = 0;
    size += ros::serialization::serializationLength(seq);
    size += ros::serialization::serializationLength(stamp);
    size += ros::serialization::serializationLength(frame_id);
    return size;
  }

  typedef boost::shared_ptr< ::std_msgs::Header_<ContainerAllocator> > Ptr;
  typedef boost::shared_ptr< ::std_msgs::Header_<ContainerAllocator>  const> ConstPtr;
  boost::shared_ptr<std::map<std::string, std::string> > __connection_header;
}; // struct Header
typedef  ::std_msgs::Header_<std::allocator<void> > Header;

typedef boost::shared_ptr< ::std_msgs::Header> HeaderPtr;
typedef boost::shared_ptr< ::std_msgs::Header const> HeaderConstPtr;

相关

我认为以下内容并不重复:

  1. 什么是allocator<T> - 不是重复问题,因为我询问的是当Tvoid时的特定情况,而不是std::allocator<>的一般情况。
  2. std::allocator<void>的弃用 - 不是重复问题,因为我不想知道为什么它已在C++20中被弃用或更改,我想了解std::allocator<void>的一般情况,它是做什么的,何时/为什么要使用它。
  3. https://answers.ros.org/question/212857/what-is-constptr/

1
@KarlKnechtel 这个问题似乎是关于Tvoid的,这有点特殊。 - Daniel Langr
1
@DanielLangr,“std::allocator<void>并非已弃用,只是它不是一个显式的特化。”参见:https://dev59.com/cVUL5IYBdhLWcg3whIO-#54093125. - Gabriel Staples
1
这个答案可能会有用:https://dev59.com/cVUL5IYBdhLWcg3whIO-#50248203。 - Daniel Langr
1
@GabrielStaples 你说得对,只是显式特化已经被弃用/移除了。 - Daniel Langr
2
@DanielLangr,“我不确定是否值得尝试理解与C++11之前的问题相关的事情。”上面使用的ROS代码在许多专业代码库中都被广泛使用,甚至包括今天使用C++17的代码库,包括我自己的代码库。我认为它值得进一步理解和必要的工作,特别是因为Stack Overflow上的某些用户已经知道答案,并且可以通过分享他们的知识提供很好的服务。 - Gabriel Staples
显示剩余7条评论
1个回答

6

std::allocator<void> 是一种分配器类型,它仅用于通过 rebind 模板声明其他特定对象的分配器类型。

在您的情况下,Header 类型定义基本上只是说默认分配器为 std::allocatorHeader_ 使用它来创建 std::allocator<char> 用于 frame_id。我想从风格上讲,可能最好一开始就用 std::allocator<char>(在类型定义处),因为此时 Header_ 仅将其用于 std::string,但是 Header_ 看起来不像是普通的 char 容器,如std::stringstd::vector,所以显式指定通用的 std::allocator<void> 更有意义。而且,在这种情况下更重要的可能是在脚本或者自动生成代码的模板中使用这样的分配器更加容易。

更多信息请参见:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接