Ver*_*ple 2 c++ containers stdlist reinterpret-cast
reinterpret_cast使用转换std::list<Derived *>为安全吗std::list<Base *>?
class Base {
...
}
class Derived : public Base{
...
}
void func(const std::list<Base *> &list);
int main() {
std::list<Derived *> list1;
// ...
func(*reinterpret_cast<std::list<Base *> *>(&list1)); // Safe ?
}
Run Code Online (Sandbox Code Playgroud)
如果是安全的转换,我们不需要复制列表,这可能会提高性能。
无论容器模板如何,此代码都具有未定义的行为std::list<Base*>:并且std::list<Derived*>是不相关的类型。甚至std::vector<int*>与std::vector<const int*>无关。
原因之一是允许这些转换将允许添加错误reinterpret_cast<std::list<Base*>&>(derived_list).push_front(base_ptr)类型的指针。出于同样的原因,不能隐式转换为; 不幸的是,允许的转换没有容器类型的类似物。C++ 类型系统并没有那么强大。char**const char**const char* const*
\xe2\x80\x99s 确实,明显的实现将按照您对这样的强制转换的预期进行操作,因为布局都是相同的,但对于像这样的代码,非明显的实现可能会 \xe2\x80\x9cmisbehave\xe2\x80\x9d 任意这。真正的答案是接受func一个范围而不是特定的容器类型,这使得它可以与std::list<Derived*>、std::vector<Base*>和std::generator<std::unique_ptr<Base>>一起使用。
这是错误的。即使您可以将cast a重新解释Derived*为a Base*,您也无法以有意义的、可移植的方式将cast a重新解释std::list<Derived*>为a 。std::list<Base*>它们是两种不相关的类型。除了是同一模板的实例化之外,作为同一模板的实例化并不强加它们之间的任何关系。
reinterpret_cast经常被误解为任意转换,但事实并非如此。实际上,它的有效用例集相当有限。有关完整列表,请参阅此处: https: //en.cppreference.com/w/cpp/language/reinterpret_cast。将 a 转换std::list<Derived*>为 astd::list<Base*>并不在其中。
也许您不必首先复制该列表。如果类型是多态的,则不需要复制或转换,您可以使用std::list<Base*>和 elements 虚拟方法。但是,如果您确实需要将 a 转换Derived*为 a Base*,那么您可以通过 转换元素,dynamic_cast而无需转换整个列表。也不需要副本。