【问题标题】:Return reference to a vector member variable返回对向量成员变量的引用
【发布时间】:2023-03-03 06:22:27
【问题描述】:

我有一个向量作为类中的成员,我想通过 getVector() 函数返回对它的引用,以便以后能够修改它。将函数 getVector() 设置为 const 不是更好吗?但是,我在以下代码中收到错误“限定符在类型的绑定引用中删除...”。应该修改什么?

class VectorHolder
{
public:
VectorHolder(const std::vector<int>&);
std::vector<int>& getVector() const;

private:
std::vector<int> myVector;

};

std::vector<int> &VectorHolder::getVector() const
{
return myVector;
}

【问题讨论】:

    标签: c++ vector reference constants


    【解决方案1】:

    由于是const成员函数,返回类型不能是非常量引用。让它const:

    const std::vector<int> &VectorHolder::getVector() const
    {
       return myVector;
    }
    

    现在好了。

    为什么没问题?因为在 const 成员函数中,每个成员都变成 const 以使其无法修改,这意味着 myVector 是函数中的 const 向量,这就是为什么你如果返回reference,则还必须设置返回类型const

    现在你不能修改 same 对象。看看你能做什么,不能做什么:

     std::vector<int> & a = x.getVector();       //error - at compile time!
    
     const std::vector<int> & a = x.getVector(); //ok
     a.push_back(10);                            //error - at compile time!
    
     std::vector<int>  a = x.getVector();        //ok
     a.push_back(10);                            //ok
    

    顺便说一句,我想知道你为什么首先需要这样的VectorHolder

    【讨论】:

    • 这样的话以后就不能从返回的代码中修改返回的向量了吗?
    【解决方案2】:

    同时声明 const 和 mutable 变体并不罕见,如下所示:

    std::vector<int>& VectorHolder::getVector() {
      return myVector;
    }
    const std::vector<int>& VectorHolder::getVector() const {
      return myVector;
    }
    

    你的程序的根本问题是你从一个 const 方法返回一个非常量引用。

    std::vector<int>& VectorHolder::getVector() const {
      return myVector; // << error: return mutable reference from const method
    }
    

    所以你使用这种形式使它成为 const:

    const std::vector<int>& VectorHolder::getVector() const {
      return myVector; // << ok
    }
    

    当 this 在非 const 方法中或客户端持有非 const 引用时,您可以合法地使用非 const 方法:

    std::vector<int>& VectorHolder::getVector() {
      return myVector; // << ok
    }
    

    最后,你可以返回一个值(在某些情况下):

    std::vector<int> VectorHolder::getVector() const {
      return myVector; // << ok
    }
    

    因为副本不需要突变,也不会暴露内部数据。

    所以你最终会经常声明这两种变体。

    同时声明的结果是:

    VectorHolder m;
    const VectorHolder c;
    
    m.getVector().size(); // << ok
    c.getVector().size(); // << ok - no mutation
    
    m.getVector().push_back(a); // << ok
    c.getVector().push_back(a); // << error: attempt to mutate const reference because the const vector is returned
    

    所以一切都很顺利(除了方法的冗余)。

    【讨论】:

      【解决方案3】:

      函数getVector可以声明为const。它返回一个可以修改的引用,因此虽然实际函数不会修改类中的任何内容,但调用者将能够修改内部数据。

      声明为:

      std::vector<int>& getVector();
      

      如果您希望函数返回无法修改的向量,请在向量和函数上使用const 修饰符:

      const std::vector<int>& getVector() const;
      

      【讨论】:

        【解决方案4】:

        原因是 const 成员函数应该只返回 const 引用。这是因为在 const 函数中,每个数据成员都变为常量。

        因此,您必须以这种方式声明 getVector():

        std::vector<int> &VectorHolder::getVector() const;
        

        【讨论】:

        • 不管上述情况,暴露您的内部容器可能不是一个好主意。如果有一天您决定从矢量迁移到地图,您的用户将受到影响。我建议改为实现迭代器。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        • 1970-01-01
        • 1970-01-01
        • 2019-07-28
        • 1970-01-01
        • 2023-04-11
        • 2019-09-03
        相关资源
        最近更新 更多