【问题标题】:Use case of overloading address-of operator [duplicate]重载地址运算符的用例[重复]
【发布时间】:2018-08-17 23:07:09
【问题描述】:

我认为重载地址运算符& 是危险的,因为在实现实际需要它的模板时很容易忽略std::addressof() 的使用。不过,我想知道重载此运算符的正确用例是什么。特别是,标准库中是否有任何类(模板)可以做到这一点?最后,既然std::addressof()是从C++11开始引入的,那么有什么办法可以在C++03中获取有这个重载的对象的地址吗?

【问题讨论】:

标签: c++ c++11 operator-overloading c++-standard-library addressof


【解决方案1】:

& 在构建智能指针类时经常被重载,因为它使它们更易于使用:通常你想要裸托管指针,而不是智能指针对象的地址。

忽略 std::auto_ptr 的进化死水,自 C++11 起,std::unique_ptrstd::shared_ptr 等智能指针类已被引入标准。在该标准中引入了std::addressof,因为偶尔需要获取对象的真实地址。

std::addressof 的可能实现是微不足道的,但由于需要大量的转换,所以很臭;一个可能的实现是1

template< class T >
T* addressof(T& arg) 
{
    return reinterpret_cast<T*>(
               &const_cast<char&>(
                  reinterpret_cast<const volatile char&>(arg)));
}

重载&amp; 的其他更奇特的用途是支持 EBNF 语法解析器。 Boost Spirit 以惊人的速度做到了这一点。


1引用http://en.cppreference.com/w/cpp/memory/addressof

【讨论】:

  • std::unique_ptrstd::shared_ptr 都不会重载 &amp; 运算符,所以我不明白您的意思。
  • 标准智能指针重载*-&gt;,而不是&amp;
【解决方案2】:

不,唯一的方法是 C++11 或更高版本中的std::addressof(),或者它在早期版本中的实现,见上文:

template< class T >
T* addressof(T& arg) 
{
    return reinterpret_cast<T*>(
               &const_cast<char&>(
                  reinterpret_cast<const volatile char&>(arg)));
}

【讨论】:

  • 我不能引用章节,但我认为这是形式上未定义的行为。这就是 为什么 std::addressof 被添加到标准中;大多数实现可以只使用您拥有的代码,但如果它不起作用,他们必须创建一个 __addressof__ 关键字并让编译器识别它(或类似方法)。这与 offsetof 标准化的原因相同。
  • 你的意思是我提供的实现是未定义的?这是addressof或非常相似的实际实现!
  • 是的,我的意思是您提供的代码是未定义的。标准库是 C++ 实现的一部分。因此,它可以依赖特定编译器的行为(记住“未定义”并不意味着“不起作用”,它意味着“标准不保证它会起作用”)。对于那些试图编写可移植代码 OTOH 的人来说,依赖编译器的行为是一个坏主意(特别是,如果编译器行为发生变化,他们可以更改库以匹配)。
  • @MartinBonner 如果转换引用的行为与指针相同(正如我的直觉),它是明确定义的。 offsetof 不仅仅是强制转换,它还需要指针算术,这在数组以外的任何东西上都是未定义的
  • 但请注意,constexpr 版本需要编译器支持
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-25
  • 2015-06-20
  • 2011-10-27
  • 2021-12-02
  • 2011-11-12
  • 2012-12-22
相关资源
最近更新 更多