c++ - std::launder、std::vector 和 move 仅可构造类型
问题描述
对于我的项目的功能请求,我认为/我被建议用于在向量中移动元素,其中元素只能移动构造(未定义移动赋值运算符)。
目标是将最后一个元素移动到给定位置,然后弹出前者。std::launder
i
换句话说,生成的代码将是这样的(为此目的的简化版本):
void foo(std::vector<my_type> &vec, std::size_t i) {
my_type *el = vec.data() + i;
el->~my_type();
new (std::launder(el)) my_type{std::move(vec.back())};
vec.pop_back();
}
其中my_type
定义为:
struct my_type { const int v; };
使用的目的std::launder
是为可能的优化设置障碍,因为v
withinmy_type
是const
. 因此能够回收保留的内存vec[i]
以便用不同的实例替换包含的对象(实际上,我理论上将最后一项移动到不同的位置)。
这是一种有效的方法/解决方案,还是仍然是 UB,因为如果我做了类似的事情而没有重复出现,就会发生这种情况std::launder
?
据我了解, 的目的std::launder
是允许用户做这样的事情,因此在我看来,上面的代码片段是合法的。但如果我错了,我不会感到惊讶,所以我希望得到比我更有经验的人的反馈
---编辑
同样,我也想交换相同类型的元素。
生成的代码应该是这样的:
const auto tmp = std::move(vec[i]);
vec[i].~object_type();
new (std::launder(&vec[i])) object_type{std::move(vec[j])};
vec[j].~object_type();
new (std::launder(&vec[j])) object_type{std::move(tmp)};
我非常有信心,如果std::launder
适合第一个示例,那么出于类似原因,这个示例也应该可以正常工作。我错了吗?
解决方案
launder
给你一个指向已经存在的对象的指针。
那里没有对象。您刚刚在上一行中将其销毁。
甚至对launder
自身的调用也是纯粹的 UB。
对于这种事情,在访问新创建的对象launder
时是需要的。不是在您创建它时。
推荐阅读
- sql-server - MSSQL2014 & python 3.7.3:尝试获取存储过程返回值导致“没有结果。以前的 SQL 不是查询。”
- javascript - 如何在 dataTable 按钮之间添加 div?
- button - SwiftUI - 在视图中包装 Button,以创建自定义按钮
- java - AWS SES - 554 消息被拒绝
- tomcat - Tomcat CORS 问题,如何解决缺少 Access-Control-Allow-Origin 标头
- java - 使用构造函数的先前变量创建一个新对象
- perl - Perl 系统调用在某些情况下不起作用
- sftp - Apache Commons VFS2 getUid() 在连接到 SFTP 服务器时生成 NumberFormatException
- c# - 镜像压缩图片文件夹
- c# - C#:为什么 '\n' 是字符而不是字符串?