c – std ::洗涤槽如何影响容器?
考虑以下简化和不完整的固定大小向量的实现:
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; 索引运算符使用起始指针来访问该对象.此时的对象被pop破坏,另一个对象通过push(2)在其存储位置创建.如果我正确地阅读了关于std::launder的文档,这意味着以下行中v [0]的行为是未定义的. 如何使用std :: launder来纠正这个代码?每次使用新产品时,我们是否必须开始和结束流水? stdlib的当前实现似乎使用类似于上面发布的代码.这些实现的行为是否未定义? 解决方法
如何使用std :: launder来纠正这个代码?每次使用新产品时,我们是否必须开始和结束流水?
从P0532R0开始,您可以避免需要调用lawn(),如果将placement new的返回值分配给end.除非矢量为空,否则您不需要更改开始指针,因为由start指定的对象仍然具有您提供的代码的活动生命周期. 同一篇文章指出,除非对象生命周期已经结束并且已经被一个新的对象所替代,否则,洗牌()是无效的,所以如果没有必要,使用流水线不会导致性能损失:
stdlib的当前实现似乎使用类似于上面发布的代码.这些实现的行为是否未定义? 是. P0532R0还讨论了这个问题,内容类似于问题评论中的讨论:向量不直接使用布局新,放置新调用的返回值在向量的分配器的函数链中丢失,并且在任何事件布局新的元素使用元素,所以构建内部向量机器不能使用返回值.洗衣()似乎是这里打算使用的工具.然而,由allocator指定的指针类型根本不需要是一个原始指针类型,而launder()只适用于原始指针.目前的实施方式目前尚未定义为某些类型;流氓()似乎不是用于解决基于分配器的容器的通用情况的适当机制. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |