简体   繁体   English

在 std::set 的定义中将 const_iterator 转换为 iterator&

[英]Cast of const_iterator to iterator& in definition of std::set

C++ STL uses a red-black tree to store data inside std::set and std::map . C++ STL 使用红黑树在std::setstd::map中存储数据。 I noticed that set::iterator is actually a typedef of the const iterator of the red black tree:我注意到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;

This is reasonable because users are supposed not to modify the content of the set through an iterator.这是合理的,因为用户不应该通过迭代器修改集合的内容。 But set has to implement operations like insert and erase , which calls for a non-const iterator of the red-black tree.但是set必须实现inserterase之类的操作,这需要红黑树的非常量迭代器。 SGI STL uses a c-style cast to do this: SGI STL 使用 c-style cast 来做到这一点:

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

I'm wondering:我在想:

  1. Why is this cast safe?为什么这个演员是安全的? It is casting _Rep_type::const_iterator to _Rep_type::iterator& .它将_Rep_type::const_iterator转换为_Rep_type::iterator&
  2. How to write the cast in C++ style?如何以 C++ 风格编写演员表? I've tried to do it : Neither static_cast nor const_cast will do the job.我试过这样做static_castconst_cast都无法完成这项工作。 reinterpret_cast can compile, but I'm not sure if it does the same thing as the C-style cast. reinterpret_cast可以编译,但我不确定它是否与 C 风格的转换有同样的作用。

iterator and _Rep_type::iterator are instances of the same class template, the former using const qualified types and the latter using the same, but non- const types. iterator_Rep_type::iterator是同一类模板的实例,前者使用const限定类型,后者使用相同但非const类型。 Something like this:是这样的:

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

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

So for your questions:所以对于你的问题:

  1. It is safe because the two types have the exact same memory layout.这是安全的,因为这两种类型具有完全相同的内存布局。
  2. You cannot use static_cast because the compiler considers the types to be unrelated.您不能使用static_cast ,因为编译器认为类型不相关。 You have to bring in the heavy artillery, reinterpret_cast :你必须带上重炮, reinterpret_cast
int test() {
    S s;
    Sconst& sconst = reinterpret_cast<Sconst&>(s);
}

A C-Cast has no direct mapping to one specific C++ cast. C-Cast 没有直接映射到一个特定的 C++ 转换。

But a C-Cast can be mapped to one or more C++ casts.但是 C-Cast 可以映射到一个或多个 C++ 转换。

When doing a C-Cast you can think of the compiler trying this set of C++ casts in order.在执行 C-Cast 时,您可以认为编译器按顺序尝试这组 C++ 强制转换。 The first one that is valid is what the C++ compiler will do: (see also C++ Standard , In N4917 7.6.3 Explicit type conversion (cast notation) [expr.cast])第一个有效的是 C++ 编译器将执行的操作:(另请参阅C++ 标准,在N4917 7.6.3 显式类型转换(强制转换符号)[expr.cast] 中)

  1. const_cast const_cast
  2. static_cast静态投射
  3. static_cast followed by const_cast static_cast 后接 const_cast
  4. reinterpret_cast重新诠释
  5. reinterpret_castfollowed by const_cast reinterpret_cast 后接 const_cast

So looking at your example, it looks like option 3 or 5 (but would need to try it with a compiler to be sure).所以看看你的例子,它看起来像选项 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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM