【发布时间】:2015-01-24 02:02:34
【问题描述】:
考虑以下程序:
#include <algorithm>
#include <iostream>
#include <vector>
struct foo {
foo(int value)
: value_(value)
{
// perform range checks
}
int value() const {
return value_;
}
private:
int value_;
};
int main() {
std::vector<foo> values{0, 1, 2, 3, 4, 5};
std::for_each(std::begin(values), std::end(values),
[](foo& f){ std::cout << f.value(); });
std::cout << std::endl;
std::for_each(reinterpret_cast<const int*>(values.data()),
reinterpret_cast<const int*>(values.data()) + values.size(),
[](int i){ std::cout << i; });
}
使用 Apple LLVM 6.0 版 (clang-600.0.54)(基于 LLVM 3.5svn)编译后,它会产生以下输出(这正是我想要的):
012345
012345
第一次迭代很简单。然而,第二次迭代不是通过迭代器执行的,而是通过指向已转换为const int* 的底层存储的指针。
我的问题是:该代码合法吗?
我的直觉是。根据 C++11 标准的§5.2.10/7(最终工作草案):
当“指向
T1”的指针类型的纯右值v被转换为类型 “指向cvT2的指针”,如果T1和T2都是static_cast<cvT2*>(static_cast<cvvoid*>(v))标准布局类型 (3.9) 和T2的对齐要求是 不比T1更严格
如果我解释正确,那么上面的代码应该是正确的,对吧?如果没有,可以让它工作吗?
【问题讨论】:
-
有一件事是肯定的:这不违反严格的别名(因为结构有一个
double对象作为它们的初始成员)。这让我想起了std::complex<T>的要求,即它的地址必须可转换为两个Ts 数组的第一个元素(即T *)。所以我想在这种情况下不允许尾随填充,你会很安全。 -
谢谢,我想这很可能是一个答案。
-
:) 我不这么认为——只是因为我没有基于标准的证据来支持它……只是一个例子。这很好,但不能保证:)
-
std::complex<T>有一个特殊条款说它必须工作
标签: c++ pointers c++11 struct strict-aliasing