将超出作用域的对象地址存入std::map是否属于未定义行为?
问题结论
仅读取已销毁对象地址转换得到的整数值,不属于未定义行为
详细解释
- 你在对象存活阶段将其地址通过
reinterpret_cast转换为unsigned long整数的操作本身是合法的,转换后得到的是独立的普通数值,和原对象的生命周期不再有绑定关系 - 后续你将该整数存入
std::map、读取该数值的操作,都属于对普通整数变量的常规操作,完全不涉及对原对象的访问,不存在野指针相关的风险 - 只有当你后续将该整数转换回指针类型,并且尝试解引用访问已经销毁的对象时,才会触发未定义行为
代码示例说明
std::map<unsigned long, std::string> index; // 对象存活阶段转换地址,操作合法 { std::string tmp_obj = "demo"; unsigned long addr_val = reinterpret_cast<unsigned long>(&tmp_obj); index[addr_val] = "tmp_obj对应的记录"; } // 此处tmp_obj已经销毁 // 仅读取map中存储的地址整数值,完全合法 for (const auto& entry : index) { // 读取entry.first(地址对应的整数值)和entry.second都没有问题 std::cout << "地址0x" << std::hex << entry.first << "对应的记录为:" << entry.second << "\n"; } // 只有执行类似如下操作时才会产生未定义行为 // auto test_ptr = reinterpret_cast<std::string*>(index.begin()->first); // std::cout << *test_ptr << "\n"; // 解引用指向已销毁对象的指针,属于UB
内容的提问来源于stack exchange,提问作者Lorah Attkins
相关产品推荐
相关产品推荐

