为什么通过 const 函数获取 std::vector 元素的 return 地址是错误的?

Why is it erroneous to return address of a std::vector element via a const function?

我查看了以下线程,但它们没有讨论 const地址返回函数的特性:

(1) Returning a pointer to a vector element in c++

(2) It's safe to return address of a std::map value?

代码中:

class test_c{
    private: 
        std::vector <double> dblvec;
        double *dblarray;
    public:
        double *AddVecElem(int index){return &dblvec[index];} //Fine
        double *AddVecElem(int index) const {return &dblvec[index];} //compiler error "Return value type does not match function type"
        double *AddArrElem(int index){return &dblarray[index];}//Fine
        double *AddArrElem(int index) const {return &dblarray[index];}//Fine
};

只有将矢量元素的地址作为 const 函数返回的情况才会产生编译器错误。

这是为什么?返回向量元素的地址如何影响对象的状态?

因为 dblvec[index]const 函数中会调用:

const_reference operator[]( size_type pos ) const;

并且 &dblarray[index] 属于 const double * 类型,无法转换为 double *

dblarray[index] 另一方面是 double 所以你 return 是 double *

如果您在 const 函数中,请查看问题 What can a 'const' method change? 以了解有关什么是 const 的更多详细信息。

如果您将函数声明为 class const 函数,这意味着您不能从函数中更改 class 的变量,也不能 return 地址class 的变量,除非您保证此函数 return 是一个不可更改的(常量)值。

const 函数内部,函数将 class 的变量视为 const 变量,因此当您尝试 return 地址时,您实际上return const double * 而不是函数要求的 double *

这种情况的解决方案是 return 指向 const T 的指针:

const double* AddVecElem(int index) const {return &dblvec[index];}

或者,正如您提到的将此函数声明为非常量函数。

另一个解决方案是return一个非指针值(值的副本),然后使用void setValue(..)函数来改变这个class的变量数据。

至于 double *dblarray 你的函数没有 return 指针本身,它 return 是你变量的副本(注意 - 你的函数 returns double* 并且变量在同一指针级别内 - 所以它 return 是一个副本)。就像下面的例子:

private:
    int value;
public:
    int return_value() const {
        return value; // Copy of the const returns - you don't change class's variable data
    }
    int* return_pointer_value() const {
        return &value; // Compiler error - expected int* returns const int*
    }

所以,如果你想让指针的情况等于向量的情况,你应该 return double** 而不是 double*:

double **AddArrElem(int index) const {
    return &dblarray; // Compiler error - expected double** returns const double *const*
    // (*const)=> for 'dblarray', (*)=> for '&'
}

那么为什么向量的行为不同?为什么你不能 returns &dblvec[index]? 如@t.niese post 中所述,对 vector 的运算符函数的调用识别出它是一个 const 向量,因此它自动 returns const double- 让我们看一下这个函数:

double& AddVecElem(int index) const {
    return dblvec[index]; // Compiler error - Expected double returns const double
}

我们想return引用这个变量,但是returned变量是一个常量。所以当你想要 return double* 你实际上 returns const double*.

即使您尝试绕过并调用 vector.data(),它 return 也是您 const double * 而不是 double* - 这就是两者之间的区别矢量和指针。

作为参考:Can const member function return a non-const pointer to a data member?