我对函数返回有点困惑,我的目的是尽量避免复制。
我读了一些文档,告诉我不要使用reference作为map的值。
但在下面的代码中,我感到困惑。
struct BigCls {
// this struct has a expensive constructor
BigCls(...);
};
// solution 1
void create_function() {
std::map<int, BigCls> m;
m[1] = BigCls(...);
m[2] = BigCls(...);
...
}
BigCls get(int a) {
return m.at(a);
}
// solution 2
void create_function() {
std::map<int, BigCls*> m;
m[1] = new BigCls(...);
m[2] = new BigCls(...);
...
}
BigCls* get(int a) {
return m.at(a);
}
// solution 3
void create_function() {
std::map<int, BigCls&> m; // i think if map's value is reference, then the cls should be static
// or it will fail, am i right?
static BigCls cls(...);
m[1] = cls;
...
}
BigCls& get(int a) {
return m.at(a);
}
哪一个最快?你认为哪一个是最好的?
std::map
t&at(常量键和键);
(1)(自C++11)常量t&at(常量键和键)常量;
(2)(自C++11)
返回对key与key等效的元素的映射值的引用。如果不存在这样的元素,则抛出std::out_of_range
类型的异常。
(cppreference)
std::map::at
返回元素引用,因此不存在复制行为(除非您将其返回值赋给非引用变量)。
问题中的代码有问题,m
变量不应该在函数内部。
除了这个问题之外,将解决方案1中的get
函数的返回类型从bigcls
更改为bigcls&
将是最好的解决方案。
struct BigCls {
BigCls(...);
int v1, v2;
};
std::map<int, BigCls> m;
void create_function() {
m[1] = BigCls(...);
m[2] = BigCls(...);
...
}
BigCls& get(int a) {
return m.at(a);
}
void examples()
{
int v1 = get(1).v1;
BigCls &bigCls2 = get(2);
int v2 = bigCls2.v2;
}
您不需要在映射中存储引用就可以获得对映射中值的引用。这里:
std::map<int,BigCls> m;
BigCls& get(int a) {
return m.at(a);
}
您正在返回对映射中值的引用。如果你这样称呼它,就不会复制:
BigCls& x = get(42);
在映射中存储指针是不必要的复杂,除非您实际需要该级别的间接(例如当bigcls
是多态类型时)。
哪一个最快?你认为哪一个是最好的?
这听起来像是过早的优化。根据需要副本还是引用,选择返回副本或引用。它意味着函数的不同语义。担心性能是因为您有正确的代码,并且通过分析和测量,您发现它需要改进。