c ++如何创建一个即使在对象被覆盖时也会持续的指针?

Posted

技术标签:

【中文标题】c ++如何创建一个即使在对象被覆盖时也会持续的指针?【英文标题】:c++ how to create a pointer that will last even when object is overwritten? 【发布时间】:2019-07-12 09:20:55 【问题描述】:

我正在创建一个<int, Foo*> 类型的std::map。我正在使用 emplace 函数在 for 循环中填充此映射。在这个循环中,我在每次循环迭代时创建一个 Foo 对象 Foo f = Foo() 并将其插入到映射中,如下所示:

std::map<int, Foo*> mymap;
for(int i = 0 ; i < 4; i ++)

    Foo f = Foo();
    mymap.emplace(i, &f);
    mymap[i]->a.pushback(pow(i,2));

其中avector&lt;int&gt;Foo 问题很清楚。我在mymap 中插入了对f 的引用,而在下一次迭代中,我正在重新创建f,使之前指向f 的指针过时。我怎样才能解决这个问题,同时仍然在mymap 中保留指向f 的指针,而不是存储f 的副本?智能指针是解决方案吗? (我以前从未使用过它们)。

【问题讨论】:

我不确定我是否理解您的意图。你现在这样做的方式,f 在循环结束时是无效的,所以你的指针指向无效的内存。尝试使用Foo *f = new Foo;,这样您的地图就会在堆上存储指向Foo 对象的指针(在delete 之前有效)。另外,我不确定i^2 是否是故意的,这是按位异或而不是平方。 "使指向 f 的前一个指针过时" 这不是关于过时的数据,而是关于引用一个非孤立的现有对象!您从堆栈上的对象创建一个指针。离开循环体后,对象不再存在,指针仍指向死对象。那是未定义的行为 @Klaus 是对的。这正是我想要解决的。我发现之前的指针都指向了最近创建的f,而循环还在迭代。 【参考方案1】:

使用new

mymap.emplace(i, new Foo());

有关new-oeprator 的更多信息,请参阅here。

【讨论】:

new Foo() 是指向对象的指针还是对象本身? new Foo() 将在堆上分配空间,在其上调用Foo::Foo 构造函数,并将地址返回给您。所以它是一个指向 Foo 对象的指针。在现代 C++ 中,建议使用 std::shared_ptr 和/或 std::unique_ptr 自动为您处理分配和释放。 @Botje 我很乐意接受您在上述示例中使用 std::unique_ptr 的回答,如果这是作为现代方法的正确方法。 不,@churill 的回答也是正确的。阅读 shared_ptr 和 unique_ptr 的文档,并确定这两种所有权模型中的哪一种符合您的意图。【参考方案2】:

你可能只是想要:

std::map<int, Foo> mymap;
for(int i = 0 ; i < 4; i ++)

    //mymap.emplace(i, Foo()); // operator[] would do similar anyway
    mymap[i].a.pushback(pow(i, 2));

或者,如果你真的想要指针语义

std::map<int, std::unique_ptr<Foo>> mymap;
for(int i = 0 ; i < 4; i ++)

    mymap.emplace(i, std::make_unique<Foo>());
    mymap[i]->a.pushback(pow(i,2));

如果你真的想要原始的拥有指针:

std::map<int, Foo*> mymap;
for(int i = 0 ; i < 4; i ++)

    mymap.emplace(i, new Foo()); // calling delete later is required to avoid leak
    mymap[i]->a.pushback(pow(i,2));

【讨论】:

谢谢。我认为理想情况下,您应该在映射中放置指向对象的指针,而不是对象本身。这就是为什么我没有使用你的第一种方法。你会从你的 3 中使用哪种方法? 我会默认将 Object 放入类中。但是例如你不能如果Foo是多态的,那么就使用智能指针。

以上是关于c ++如何创建一个即使在对象被覆盖时也会持续的指针?的主要内容,如果未能解决你的问题,请参考以下文章

“交易已中止”即使在故意中止时也会被抓住

在C++ 如何在堆中创建一个类的对象? 谢谢!

Android Dalvik虚拟机 对象创建内存分配流程

Android Dalvik虚拟机 对象创建内存分配流程

在c#中用arraylist创建的数组,在用contains查看是不是包含某一个对象时,判

静态对象成员会在所属类的析构函数被调用时自动析构吗?