C ++中的延迟实例化

时间:2018-11-20 22:33:17

标签: c++

我试图在不实例化对象的情况下创建变量。

在Python中,它看起来像这样:

graph = mymap[c] if c in mymap else Graph() 

因此,我基本上检查是否已经有该图,否则创建它。我的理解是,如果我在C ++中声明以下内容,它将调用构造函数,并且是浪费的

Graph g;

所以我试图使用指针来避免这种“浪费”:

    Graph* g;

    if (graphs.find(c) == graphs.end()){
        g = new Graph();
        graphs[c] = *g;
    } else {
        g = &(graphs[c]);
    }

    std::cout << g << std::endl;
    std::cout << &(graphs[c]) << std::endl;

问题是最后打印的地址不匹配。实际上,我的测试表明,每次都在创建一个新的Graph实例时,发生了一些奇怪的事情。

我在做什么错了?

2 个答案:

答案 0 :(得分:4)

您实际上不必在这里做任何花哨的事情。你可以简单地做

Graph* g = &graphs[c];

原因是map::operator[]具有以下行为:

  

返回对映射到与键等效的键的值的引用,如果该键尚不存在,则执行插入

因此,如果键已经具有关联的值,则将获得对该对象的引用。如果该键尚不存在,则会为您默认构造并插入一个值,并返回对该新对象的引用。

答案 1 :(得分:2)

另一个答案已经说出了正确的方法来完成您要问的事情,但是我会解决(哈!)为什么地址不匹配的问题:

在这一行:

    graphs[c] = *g;

您正在为刚用new指向的g制作的图形创建 COPY ,并且该副本具有不同的地址。然后,您正在打印原件的地址和副本的地址,因此显然它们位于不同的地址。

graphs[c] = ...

当还没有映射到c时(您已经检查过),此代码已经完成了一个(默认)Graph对象的分配和构造,该对象将存储在地图中。只是使它刚刚创建的Graph对象看起来像您先前通过调用new而创建的对象。