【发布时间】:2016-10-20 21:40:42
【问题描述】:
考虑以下固定大小向量的简化和不完整实现:
template<typename T>
class Vec {
T *start, *end;
public:
T& operator[](ssize_t idx) { return start[idx]; }
void pop() {
end--;
end->~T();
}
template<typename... U>
void push(U... args) {
new (end) T { std::forward<U>(args)... };
end++;
}
};
现在考虑以下 T:
struct T {
const int i;
};
还有以下用例:
Vec<T> v;
v.push(1);
std::cout << v[0].i;
v.pop();
v.push(2);
std::cout << v[0].i;
索引运算符使用start 指针访问对象。此时的对象被pop 销毁,另一个对象由push(2) 在其存储位置创建。如果我正确阅读了有关std::launder 的文档,这意味着下面一行中v[0] 的行为是未定义的。
应该如何使用 std::launder 来更正此代码?每次使用新安置时,我们是否必须清洗开始和结束?标准库的当前实现似乎使用与上面发布的代码类似的代码。这些实现的行为是否未定义?
【问题讨论】:
-
std::vector自 C++03 以来一直无法在标准 C++ 中实现。 -
@T.C.:愿意扩展一下吗?鉴于它,你知道,是。
-
@LightnessRacesinOrbit
data()的返回值(或在 C++03 中,&v[0])需要允许对其进行指针运算,并且指针运算仅针对指向同一数组的指针定义.vector,由于显而易见的原因,实际上不能在内部使用数组。 -
@TC:(试图确认我对您的意思的理解)假设您不将动态分配的“数组”块算作“数组”,那么您也相信我们不能合法地在
new int[N]? 上执行指针运算? -
@LightnessRacesinOrbit
vector没有newaT[N]。它分配一个存储块并将元素一个接一个地构造到该存储中。
标签: c++ undefined-behavior c++17