c++ 在std::set的定义中将const_iterator强制转换为迭代器&

2ledvvac  于 2022-12-24  发布在  其他
关注(0)|答案(2)|浏览(151)

C++ STL在std::setstd::map内部使用红黑树来存储数据,我注意到set::iterator实际上是红黑树的const迭代器的typedef:

//All code snippets taken from SGI STL. https://www.sgi.com/tech/stl/

typedef _Rb_tree<key_type, value_type, _Identity<value_type>, key_compare, _Alloc> _Rep_type;
typedef typename _Rep_type::const_iterator iterator;

这是合理的,因为用户不应该通过迭代器修改集合的内容,但是set必须实现像inserterase这样的操作,这需要红黑树的非常量迭代器,SGI STL使用c风格的强制转换来实现这一点:

void erase(iterator __position) { 
  typedef typename _Rep_type::iterator _Rep_iterator;
  _M_t.erase((_Rep_iterator&)__position); 
}

我在想:
1.为什么这个强制转换是安全的?它将_Rep_type::const_iterator强制转换为_Rep_type::iterator&
1.如何以C++风格编写强制转换?I've tried to do itstatic_castconst_cast都不能完成这项工作。reinterpret_cast可以编译,但我不确定它是否与C风格的强制转换做同样的事情。

lnvxswe2

lnvxswe21#

iterator_Rep_type::iterator是同一个类模板的示例,前者使用const限定类型,后者使用相同但非const类型。

template <class T, class U>
struct B {};

using S = B<int&, int*>;
using Sconst = B<const int&, const int*>;

所以对于你们的问题:
1.它是安全的,因为这两种类型具有完全相同的内存布局。
1.你不能使用static_cast,因为编译器认为类型是不相关的,你必须引入重型火炮reinterpret_cast

int test() {
    S s;
    Sconst& sconst = reinterpret_cast<Sconst&>(s);
}
zpjtge22

zpjtge222#

C-Cast没有到特定C类型转换的直接Map。
但是一个C-Cast可以Map到一个或多个C
类型转换。
在执行C-Cast时,你可以想象编译器按顺序尝试这组C类型转换。第一个有效的类型转换是C编译器将执行的操作:(另请参见N4917 7.6.3显式类型转换(强制类型转换表示法)[表达式强制类型转换]中的C++ Standard
1.常量_转换
1.静态强制转换

  1. static_cast后跟const_cast
    1.重新解释转换
  2. reinterpret_cast后跟const_cast
    因此,看看您的示例,它看起来像选项3或5(但需要用编译器来尝试以确定)。
(_Rep_iterator&)__position

 // Maps to:

 const_cast<_Rep_iterator&>(static_cast<_Rep_iterator const&>(__position))

 // or

 const_cast<_Rep_iterator&>(reinterpret_cast<_Rep_iterator const&>(__position))

相关问题