返回右值或左值

时间:2019-02-23 08:09:57

标签: c++ rvalue lvalue

我想定义s[i],如果从未分配过0,则返回s[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]。但是,如果我取消注释,则会出现错误。

1 个答案:

答案 0 :(得分: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;
}