C++ C++;映射,使用常量引用作为值类型,这里有什么问题?
今天我看到了我老板的代码,它使用常量引用作为C++ C++;映射,使用常量引用作为值类型,这里有什么问题?,c++,reference,stdmap,C++,Reference,Stdmap,今天我看到了我老板的代码,它使用常量引用作为映射的值类型 代码如下: class ConfigManager{ public: map<PB::Point, const PB::WorldPoint&, compare_point> world_point; //the rest are omitted }; 但是如果我改变map我的map到映射myMap,它编译 又出现了另一个问题。使用map-myMap,我不能使用[]获取该对,但我可以使
映射
的值类型
代码如下:
class ConfigManager{
public:
map<PB::Point, const PB::WorldPoint&, compare_point> world_point;
//the rest are omitted
};
但是如果我改变map我的map代码>到映射myMap代码>,它编译
又出现了另一个问题。使用map-myMap
,我不能使用[]
获取该对,但我可以使用map.find()
(在我告诉老板使用[]
无法编译后,老板让我使用map.find()
)
代码示例2
如果我正确理解输出(如果我理解错误,请纠正我),则表明:
make\u pair(“爱”,a)
创建对象pair
。然后将这一对插入到myMap
中
不知怎的,我不知道它是怎么发生的,一个
的临时副本立即被销毁。对我来说,这意味着一个
的临时副本的内存现在不属于任何人,如果我理解正确,它现在是一个可用的内存空间,可以用任何值填充
所以现在我又感到困惑了
我的问题是:
代码示例3发生了什么变化?我的理解正确吗?为什么一个
的临时副本在语句之后立即被销毁?使用常量引用是否可以延长临时变量的生命周期?我的意思是,我认为它在main
完成之前不应该被破坏
我老板的密码是不是不正确而且很危险
为什么语句的临时副本会在语句之后立即被销毁
因为(在大多数情况下)临时工就是这样工作的。在创建它们的语句结束之前,该语句将一直处于活动状态。在这种情况下,临时生存期的延长不适用,请参阅。TLDR版本是
一般来说,临时文件的使用寿命不能通过以下方式进一步延长:
“传递”:第二个引用,从引用到
临时绑定的,不影响其使用寿命
我可以使用常量引用作为映射的值类型吗
是的,只要您意识到向映射添加常量引用对所引用对象的生存期没有影响。您的BOSS代码也不正确,因为make\u pair
返回的临时值在语句末尾被销毁。您可以使用std::unique\u ptr
示例3的代码会发生什么变化?我的理解正确吗
你的解释很贴切。由std::make\u pair
返回的std::pair
是临时对象。临时std::pair
包含a
的副本。在表达式末尾,该对被销毁,这也会销毁其元素,包括a
的副本
为什么语句的临时副本会在语句之后立即被销毁?使用常量引用是否可以延长临时变量的生命周期?我的意思是,我认为它不应该被破坏,直到主要完成
这里的临时变量是std::make_pair
的结果,它被用作成员函数insert
的参数。此处适用的相关规则包括:
每当引用绑定到临时对象或其子对象时,临时对象的生存期将延长以匹配引用的生存期,但以下情况除外:
- [……]
- 在包含该函数调用的完整表达式结束之前,函数调用中引用参数的临时绑定一直存在[…]
- [……]
包含函数调用的完整表达式是表达式myMap.insert(make_pair(1,a))
这意味着std::make_pair
结果的生存期在函数返回后结束,包括它包含的A
。新的std::map
元素将引用临时std::pair
中的A
,它将在insert
返回后变为悬空
我老板的密码是不是不正确而且很危险
是的,myMap
包含悬空引用。如果问题太长,很抱歉。我已经尽力把它缩短。这让我相信你老板的代码并没有按预期的那样工作。地图引用的对象似乎与原始对象不同。底线应该是,即使它确实按预期工作,但它导致这一级别的研究的事实表明,无论如何都应该避免它。@FrançoisAndrieux是的,没有看太长的代码这会从提到std::ref
@StoryTeller UnslanderMonica中受益,std::ref
在这里可以做什么?@Rick-它可以用来创建一对,其中包含a
的引用包装,而不是副本。因此,使用a
(而不是悬挂)来初始化地图中的项目。对不起,我不明白您的答案。在这种情况下,哪一条规则适用于临时对象的生存期不会延长?如果您的答案可以更长,我们将不胜感激。我们的目标似乎是要有一个地图,它引用了地图之外存在的元素。我不确定这个答案是否是等效的。由于C++14中有std::make_unique
在初始化std::unique_ptr
s时替换new T
。在典型的现代C++中,<>代码> new < /C++ >的唯一用例是现在的布局。在C++ 20中,对于操作符new的演绎有增强。如果目标是引用现有对象,则不会使用临时对象。原始指针最适合只用于观察者的解决方案。谢谢您的帮助。但我不是在寻找替代方案。我更想知道为什么。我想指出的是,它是std::pair
,而V
恰好是一个参考类型,但map
本身的value\u类型
不是一个。不管怎样,我得到了
struct A {
int x = 3;
int y = 4;
};
map<int, A&> myMap;
int main() {
A a;
myMap.insert(make_pair(1, a));
}
struct A {
int x = 3;
int y = 4;
};
map<int, const A&> myMap;
int main() {
A a;
myMap.insert(make_pair(1, a));
//can't compile
cout << myMap[1].x << " " << myMap[1].y << endl;
//can work
//auto it = myMap.find(1);
//cout << it->second.x << " " << it->second.y << endl;
}
#include <map>
#include <iostream>
#include <string>
using namespace std;
struct A {
int x = 3;
int y = 4;
~A(){
cout << "~A():" << x << endl;
x = 0;
y = 0;
}
};
map<string, const A&> myMap;
int main() {
A a;
cout << a.x << " " << a.y << endl;
myMap.insert(make_pair("love", a));
a.x = 999;
cout << "hello" << endl;
auto s = myMap.find("love");
cout << s->second.x << " " << s->second.y << endl;
}
3 4
~A():3
hello
0 0
~A():999
using value_t=std:: unique_ptr<A>;
std::map<int, value_t> myMap;
myMap.emplace(1,new A);
myMap[1]=new A{5,6};
myMap[1]->x=7;