c – std ::洗涤槽如何影响容器?

c – std ::洗涤槽如何影响容器?,第1张

概述考虑以下简化和不完整的固定大小向量的实现: template<typename T>class Vec { T *start, *end;public: T& operator[](ssize_t idx) { return start[idx]; } void pop() { end--; end->~T(); } template<typename 考虑以下简化和不完整的固定大小向量的实现:
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指定的对象仍然具有您提供的代码的活动生命周期.

同一篇文章指出,除非对象生命周期已经结束并且已经被一个新的对象所替代,否则,洗牌()是无效的,所以如果没有必要,使用流水线不会导致性能损失:

[…] the type of std::launder(this) is equivalent to just this as Richard Smith pointed out: Remember that launder(p) is a no-op unless p points to an object whose lifetime has ended and where a new object has been created in the same storage.

stdlib的当前实现似乎使用类似于上面发布的代码.这些实现的行为是否未定义?

是. P0532R0还讨论了这个问题,内容类似于问题评论中的讨论:向量不直接使用布局新,放置新调用的返回值在向量的分配器的函数链中丢失,并且在任何事件布局新的元素使用元素,所以构建内部向量机器不能使用返回值.洗衣()似乎是这里打算使用的工具.然而,由allocator指定的指针类型根本不需要是一个原始指针类型,而launder()只适用于原始指针.目前的实施方式目前尚未定义为某些类型;流氓()似乎不是用于解决基于分配器的容器的通用情况的适当机制.

总结

以上是内存溢出为你收集整理的c – std ::洗涤槽如何影响容器?全部内容,希望文章能够帮你解决c – std ::洗涤槽如何影响容器?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/1251468.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存