对象的地址可以更改吗?

时间:2019-02-18 12:30:40

标签: c++ stdmap

我想在插入自定义对象键和双精度值的地方使用std::map(或概率std::unordered_map),例如std::map<CustomClass,double>。 对象的顺序无关紧要,只是(快速)查找很重要。我的想法是插入对象的地址/指针,因为它已经定义了一个比较器,即std::map<CustomClass*,double>

Pointers as keys in map C++ STL 有人回答说可以做到这一点,但我仍然担心可能会有一些副作用,以后很难发现。

具体来说: 在程序运行期间,对象的地址可以更改吗?这会导致我在地图中查找的行为不确定吗?

测试程序可以是:

auto a = adlib::SymPrimitive();
auto b = adlib::SymPrimitive();

auto c = adlib::mul(a,b);
auto d = adlib::add(c,a);

// adlib::Assignment holds std::map which assigns values to a,b
auto assignment = adlib::Assignment({&a,&b},{4,2});
// a=4, b=2 -> c=8 -> d=12
adlib::assertEqual(d.eval_fcn(assignment), 12);

这是用户代码,因此用户可以将变量放入向量等中。

更新: 答案让我考虑了用户可能将SymPrimitives插入向量中的情况,一个简单的情况是:

std::vector<adlib::SymPrimitive> syms{a,b};
auto assignment = adlib::Assignment({&syms[0],&syms[1]},{4,2}); // not allowed

这里的陷阱是syms[0]a的副本,并且具有不同的地址。请注意,我可能要对用户负责。

2 个答案:

答案 0 :(得分:2)

  

在程序运行时对象的地址可以更改吗?

不。对象的地址永远不变。

但是,当对象的生存期结束时,对象可以停止存在于其创建的地址。

示例:

std::map<CustomClass*,double> map;
{
    CustomClass o;
    map.emplace(&o, 3.14);
}
// the pointer within the map is now dangling; the pointed object does not exist

还请注意,对容器进行的某些操作会导致容器中的元素占据一个新对象,而旧的则被破坏。经过这样的操作后,对这些元素的引用(一般而言;包括指针和迭代器)无效,并且尝试通过这些引用进行访问的行为未定义。

答案 1 :(得分:0)

对象在其生存期内永远不会更改地址。如果您要做的就是查找与某个对象相关联的某个值,而该对象的地址在查找时是已知的,那么使用该对象的地址作为映射中的键应该是绝对安全的。

(如果对象已被销毁和/或释放,则很安全,只要您不取消引用指针,而仅将其用作在地图中查找项目的键即可。但是您可能想要弄清楚如何在对象被破坏或由于其他原因而不再在地图中时从地图中删除条目...)