Kal*_*Kal 8 c++ templates function-templates
我正在阅读std::uninitialized_copy并发现了一个叫做voidify:
效果: 相当于:
Run Code Online (Sandbox Code Playgroud)for (; first != last; ++result, (void) ++first) //#1----vvvvvvv----------->what does this call to voidify mean here ::new (voidify(*result)) typename iterator_traits<NoThrowForwardIterator>::value_type(*first);
经过进一步查找voidify,我发现它是一个函数模板:
本节中指定的一些算法使用仅说明函数 voidify:
Run Code Online (Sandbox Code Playgroud)template<class T> constexpr void* voidify(T& obj) noexcept { //#2------vvvvvvvvvv-------------------------------->why does this const_cast to void* is needed return const_cast<void*>(static_cast<const volatile void*>(addressof(obj))); //#3------------------------^^^^^^^^^^^------------->why this static_cast to const volatile void* is needed }
正如我们所看到的,它voidify返回了void*toobj或其他我不太明白的东西,因为涉及到一些强制转换,我不知道为什么需要它们。我已发表评论表明我的疑问。有人可以逐步告诉我为什么voidify需要new (voidify(*result))以及为什么const_cast需要static_cast。
总之(只是为了清楚地表达我的疑问)我的问题是:
为什么我们需要打电话voidify进来new (voidify(*result))。我知道这是使用 palcement-new,但我不知道作为参数调用voidify和传递,然后使用placement-new 的返回值的原因。*result
为什么const_cast这里用的是. reinterpret_cast为什么不是像or 之类的其他演员呢static_cast?这就是这里需要选择的const_cast。
为什么static_cast这里使用的是而不是其他一些演员。
为什么我们不能只写return addressof(obj);or return (void*)(addressof(obj);.
请注意,我试图了解该equivalent to版本的工作原理。我在不同部分提出问题的原因是因为我认为将其分为单独的步骤,然后理解这些单独的步骤可以让我们更好地理解一个主题。归根结底,我想知道它是如何工作的equivalent version。
为什么我们需要在new(voidify(*result))中调用voidify。我知道这是使用 palcement-new 但我不知道我们是否调用 voidify 并将 *result 作为参数传递,然后使用 Placement-new 的返回值。
首先要指出的是,在很多情况下,代码可以在没有 的情况下工作voidify,因此,如果您的直觉认为它可以在没有 voidify 的情况下工作,这就是原因。是voidify为了防止存在多个重载版本的情况operator new,并且会选择其中一个而不是放置 newoperator new(size_t, void*);
为什么这里使用const_cast。为什么不使用其他类型的转换,例如reinterpret_cast 或static_cast。这就是这里选择const_cast的需要。
为什么这里使用 static_cast 而不是其他一些强制转换。
如果你想草率一点,你也可以只用一个 C 风格的强制转换来做到这一点,如下所示:
return (void*) addressof(obj);
Run Code Online (Sandbox Code Playgroud)
但每个const_cast和 的static_cast作用都不同,您可能需要其中一种或两种类型的转换。您可以替换static_cast为reinterpret_cast,但它不会给您带来任何好处,并且可能会使捕获某些错误变得更加困难,因此此时您最好使用 C 风格的强制转换。
为什么我们不能只写 return addressof(obj); 或返回 (void*)(addressof(obj);。
如果您碰巧有一个超载的 . 则前者会意外失败operator new(std::size_t, decltype(addressof(obj))。正如前面提到的,后者(C 风格的演员阵容)非常好。