为const非字面量类型启用std::move是否属于未定义行为?
含const字面量类型成员类的移动操作UB判定疑问
const成员字面量类型变量存在一个问题:std::move默认会调用拷贝构造函数而非移动构造函数,这使得包含const字面量类型成员的类的移动赋值仅能在不安全的异常场景下实现。
以下代码看似可以实现对const类型对象内容的实际移动:
#include <string> #include <iostream> #include <type_traits> template<class T> std::remove_const_t<T>& de_const(T& obj) noexcept { return *static_cast<std::remove_cv_t<T>*>(const_cast<void*>(static_cast<const volatile void*>(&obj))); } struct A { const std::string s; }; int main() { A a{ "asdfasdasdfasdfasdfasdf" }, b{ "12341234123412341234" }; std::destroy_at(&a.s); std::construct_at(&de_const(a.s), std::move(de_const(b.s))); std::cout << "a.s=" << a.s << "\n"; // a.s现在存储原b对象的内容 std::cout << "b.s=" << b.s << "\n"; // b对象仍处于有效状态,但内部资源已被移走 /* 预期输出 a.s=12341234123412341234 b.s= */ }
相关已知规则与疑问:
- 自C++20起,使用
std::construct_at将已析构的const std::string透明替换为新的std::string属于合法操作 - 原作者猜测:将移动源字符串通过自定义的
de_const工具移除const限定后传入移动构造的操作,从C++技术规范层面判断属于未定义行为(UB) - 明确的UB场景:如果字面量类型本身是完整const对象,上述修改操作明确为UB;示例中结构体A的
s成员不属于该场景
核心问题:上述代码中的实现是否属于未定义行为?
实际测试结果:该代码在MSVC、GCC、Clang编译器下均可成功运行,输出结果与预期一致。
内容的提问来源于stack exchange,提问作者doug
相关产品推荐
相关产品推荐

