为什么通过 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?
我查看了以下线程,但它们没有讨论 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?