在评论中考虑以下函数:
map<vector<a>, b> func() {
map<vector<a>, b> x;
//add values of to x.
return x; //Everything gets copied and the local variable dies. Not good when your x is very big, lets say in MB s
}
map<vector<a>, b> *func() {
map<vector<a>, b> *x;
x = new map<vector<a>, b>(); //allocate the object.
b _b;
a random;
vector<a> y;
y.push_back(random);
//add values of to x.
x->insert(make_pair(y, _b));
return x; //Pointer is returned. Not sure what would happen to keys of map. Will they be copied again?
}
我对上图的另一个问题是find()
的复杂性会怎样?我认为它应该与vector的默认比较器相同,用于相应地对元素进行排序。如果我错了,请纠正我。
map<vector<a> *, b> *func() {
map<vector<a>, b> *x;
x = new map<vector<a> *, b>(); //allocate the object.
b b_;
a random;
vector<a> *y = vector<a>();
y->push_back(random);
//add values of to x.
x->insert(make_pair(y, b_));
return x; //Pointer is returned. Not sure what would happen to the elements of the keys of the map.
//In other words I mean will variable 'random' be copied again on function return. Will they be copied again?
}
答案 0 :(得分:2)
您正在尝试过早优化,从而导致潜在的灾难。
return x
,如果编译器优化是&#34; on&#34; (在编译器上使用-O3
标志)并且编译器不是完全愚蠢的,不会产生副本。简单x
将被分配到调用者堆栈空间并在函数内部引用。
你的第二次尝试(返回一个指针)有效,但是在适当的控制资源分配方面会产生问题:你在函数内调用new
,但是应该调用delete
的人和时间?可能使用智能指针(如std::unique_ptr
)会有所帮助:当没有人再存储指针时,创建的地图将被删除。
你的第三次尝试根本行不通。
vector<a> *y = vector<a>();
甚至无法编译(将vector<a>
分配给vector<a>*
?!?),然后地图将包含...指针作为键。除非您没有提供比较功能,否则地图将按照矢量的地址进行排序,而不是内容!没有人会照顾他们的毁灭。
你还会冒另一个风险:因为地图包含指针作为键,所以没有人授予矢量的常数:如果&#34;键&#34;那么,地图排序顺序的正确性会发生什么?由于这个功能的一些错误而被改变了?
答案 1 :(得分:0)
第一次尝试导致复制,但编译器将执行令人讨厌的优化工作,这可能是最常见的。不会有复制,但只是为了确定你可以写:
std::map<std::vector<a>,b> func() {
return map<vector<a>, b>() ;
}
第二次尝试引导在堆上创建的对象。放置在容器内的对象将复制到
中x->insert(make_pair(y,b));
因此它们的寿命与容器的寿命有关。
然后你负责删除指针上的地图调用删除,这不是最好的做法,但你会看到周围发生的事情。
当您调用map成员函数时,find的复杂性是对数的,如果在对象上调用静态版本,则为linear。您的密钥上最多将进行线性比较,这是一个向量。
第三次尝试使用指向向量的指针(需要新的)
std::vector<a> * y = new vector<a>;
基本上你应该在地图上修改你的密钥
std::map<vector<a> *, b>
需要您修改func()的签名以适当地返回类型。
或取消引用该对象以进行复制
x->insert(make_pair(*y,_n));
结果是您还必须管理用于密钥的内存并根据需要逐个删除它们。真的胜过这个目的,只是尽量使用容器逻辑来自动管理内存。