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));
其中a
是vector<int>
类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 ++如何创建一个即使在对象被覆盖时也会持续的指针?的主要内容,如果未能解决你的问题,请参考以下文章