返回右值或左值

returning either a rvalue or an lvalue

本文关键字:返回      更新时间:2023-10-16

我想定义s[i],如果从未分配s[0]则返回0,如果之前分配了s[i]则返回对s[i]的引用(以实现稀疏数组)。 下面的代码可以做到这一点,但由于 map 的语义,每当我尝试获取其值时,它最终都会创建s[i]

struct svec{
map<int,double> vals;
/*                                                                                                
double operator[](int index){                                                                     
return (vals.count(index) > 0) ? vals[index] : 0                                                        ;                                                                           
else return 0;                                                                                  
}                                                                                                 
*/
double &operator[](int index){
return vals[index];
}
};
int main(){
svec s;
s[0] = 10;
cout << s[1] << endl;
}

我希望注释的代码用于解析表达式s[1]。 但是如果我取消注释它,我会收到一个错误。

你不能重载返回值,所以你必须坚持按引用或按值(或指针等)返回。通过引用返回的问题在于,您必须引用内存中的现有值。当然,当值在地图中时,这很好。如果不是,则必须创建默认值并将其存储在内存中。然后,您必须确保正确删除它以免泄漏内存,但也必须确保用户没有持有对值的引用,因为它会引入意外行为。

此外,您必须考虑用户可以更改您返回的值这一事实。如果返回相同的默认值,则用户可以将其更改为另一个值。然后,所有后续调用都将返回对新值的引用。每次返回时将默认值重置为 0 对于仍保留对它的引用的所有用户来说也是出乎意料的。

您可能能够以稳定的方式解决此问题,但它可能需要大量样板代码。在这种情况下,我建议将负担放在用户身上。

class SparseVector {
private:
std::unordered_map<int, double> elements;
public:
void set(int index, double value) {
elements[index] = value;
}
double& get(int index, double& optional) {
auto it = elements.find(index);
if (it != elements.end())
return it->second;
else
return optional;
}
double& get(int index) {
auto it = elements.find(index);
if (it != elements.end())
return it->second;
throw std::runtime_error(
"Couldn't find element at index " + std::to_string(index) + 
"! Use get(int index, double& optional) if you don't want errors."
);
}
}
int main() {
double default_value = 0.0;
SparseVector vector;
std::cout << vector.get(0, default_value) << std::endl;
}