C++ 中的容器:指针与引用
Containers in C++: pointers vs references
我正在尝试了解 stl 容器(特别是地图)的最佳实践,并想知道以下内容:
map<string,blah> map1;
map<string,blah*> map2;
(1) blah a = = map2["a"]
a.foo = somethingelse;
map2["a"] = a;
(2) blah& a = map2.at("a")
(3) blah a = = map2.at("a")
a.foo = somethingelse;
map2["a"] = a;
(4) blah& a = map2["a"]
(5) blah& a = map2.at("a")
(6) blah* a = *map2.find("a")
(7) blah* a = map2["a"]
我知道在指针上存储引用有以下好处 1) 不必管理自己的内存 2) 能够从地图外部访问对象(它们的内存位置不会改变),同时在引用上存储指针意味着将元素插入映射会更便宜(复制指针,而不是引用)。
其他操作呢?例如,find 的大小是对数的,这表明最好使用引用,因为内存是连续的。
我假设 (1) 和 (3) 只是个坏主意,但其他的呢?如果我的地图是读主导的,我应该使用引用,而如果它是写主导的(对象被频繁修改),我应该使用指针,这样说是否正确?
您可能看到了 "T& at(key)" 的地图,或者其他关于参考的东西?容器确实以值作为参考,但那只是为了效率。然后将它们复制到容器中。
如果您决定将值放入容器(选项 1),那么您的项目必须在插入时复制,但随后可以通过引用进行修改:
blah &a = map1["a"]
a.foo = somethingelse;
// No need to do this: map1["a"] = a;
或者,更短:
map1["a"].foo = somethingelse;
当您对值执行此操作时,地图拥有该对象并在删除地图时(以及其他时间)将其删除。
如果存储原始指针,则必须管理内存。我不建议那样做。相反,我会考虑将 shared_ptr 或 unique_ptr 放入您的地图中。如果您需要让地图之外的值保持活动状态,即使地图被破坏,您也可以这样做。
map<string,shared_ptr<blah>> map3;
shared_ptr<blah> myPtr = make_shared<blah>();
map3["a"] = myPtr;
在这里,即使地图消失了,我仍然可以使用 myPtr。指向该对象的所有内容都消失后,该对象将被删除。
现在,让我们来处理这个问题,一个接一个地陈述...
我知道在指针上存储引用有好处。你真的存储引用吗?参见 std::reference_wraper
。你知道吗,在引擎盖下,引用是指针,{只是在前端,它是一种超级严格的类型,绑定一次并在声明时绑定}
不必管理自己的内存:不,只要它是左值,就必须管理内存。由您或编译器(自动存储持续时间)
后面能够从地图外部访问对象...,同时将指针存储在引用上...会更便宜(复制指针,而不是引用).: std::map
管理它自己的内存,如果它不应该管理对象的内存,你只想存储指针。是的,为非 integral types
存储指针更便宜
其他操作呢? ...最好使用引用,因为内存将是连续的:再次,请参见第 1 点。除非您指的是值...此外,并非所有容器都将其元素存储在连续的内存中,无论是什么类型他们消费
这样说是否正确,如果我的地图是读主导的,我应该使用引用,而如果它是写主导的(对象被频繁修改),我也许应该使用指针?:不!再次参见第 1 点...这并不重要...只是 const correct
我正在尝试了解 stl 容器(特别是地图)的最佳实践,并想知道以下内容:
map<string,blah> map1;
map<string,blah*> map2;
(1) blah a = = map2["a"]
a.foo = somethingelse;
map2["a"] = a;
(2) blah& a = map2.at("a")
(3) blah a = = map2.at("a")
a.foo = somethingelse;
map2["a"] = a;
(4) blah& a = map2["a"]
(5) blah& a = map2.at("a")
(6) blah* a = *map2.find("a")
(7) blah* a = map2["a"]
我知道在指针上存储引用有以下好处 1) 不必管理自己的内存 2) 能够从地图外部访问对象(它们的内存位置不会改变),同时在引用上存储指针意味着将元素插入映射会更便宜(复制指针,而不是引用)。
其他操作呢?例如,find 的大小是对数的,这表明最好使用引用,因为内存是连续的。
我假设 (1) 和 (3) 只是个坏主意,但其他的呢?如果我的地图是读主导的,我应该使用引用,而如果它是写主导的(对象被频繁修改),我应该使用指针,这样说是否正确?
您可能看到了 "T& at(key)" 的地图,或者其他关于参考的东西?容器确实以值作为参考,但那只是为了效率。然后将它们复制到容器中。
如果您决定将值放入容器(选项 1),那么您的项目必须在插入时复制,但随后可以通过引用进行修改:
blah &a = map1["a"]
a.foo = somethingelse;
// No need to do this: map1["a"] = a;
或者,更短:
map1["a"].foo = somethingelse;
当您对值执行此操作时,地图拥有该对象并在删除地图时(以及其他时间)将其删除。
如果存储原始指针,则必须管理内存。我不建议那样做。相反,我会考虑将 shared_ptr 或 unique_ptr 放入您的地图中。如果您需要让地图之外的值保持活动状态,即使地图被破坏,您也可以这样做。
map<string,shared_ptr<blah>> map3;
shared_ptr<blah> myPtr = make_shared<blah>();
map3["a"] = myPtr;
在这里,即使地图消失了,我仍然可以使用 myPtr。指向该对象的所有内容都消失后,该对象将被删除。
现在,让我们来处理这个问题,一个接一个地陈述...
我知道在指针上存储引用有好处。你真的存储引用吗?参见
std::reference_wraper
。你知道吗,在引擎盖下,引用是指针,{只是在前端,它是一种超级严格的类型,绑定一次并在声明时绑定}不必管理自己的内存:不,只要它是左值,就必须管理内存。由您或编译器(自动存储持续时间)
后面能够从地图外部访问对象...,同时将指针存储在引用上...会更便宜(复制指针,而不是引用).:
std::map
管理它自己的内存,如果它不应该管理对象的内存,你只想存储指针。是的,为非 integral types 存储指针更便宜
其他操作呢? ...最好使用引用,因为内存将是连续的:再次,请参见第 1 点。除非您指的是值...此外,并非所有容器都将其元素存储在连续的内存中,无论是什么类型他们消费
这样说是否正确,如果我的地图是读主导的,我应该使用引用,而如果它是写主导的(对象被频繁修改),我也许应该使用指针?:不!再次参见第 1 点...这并不重要...只是 const correct