gpt4 book ai didi

c++ - 如何从(通常)返回引用(对成员数据)的成员函数返回常量

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:39:00 31 4
gpt4 key购买 nike

我正在为下/上三角矩阵(double)编写一个类。通过利用 n*n 三角矩阵只有 n*(n + 1)/2 [可能非零] 元素这一事实,我在内部只存储平面数组成员中的元素数量。

首先,我有一个“普通”(即稠密)矩阵的基类,其中 operator() 作为下标运算符,它采用行索引和列索引:

class Matrix {
public:
// [...]
virtual const double &operator()(unsigned i, unsigned j);
virtual double &operator()(unsigned i, unsigned j);
// [...]

private:
std::valarray<double> data_;
std::size_t size_;
}

// [...]
const double &Matrix::operator()(unsigned i, unsigned j) {
return data_[size_*i + j];
}

对于三角矩阵(以下我将以下三角矩阵为例),为了提供与正则矩阵相同的接口(interface),我需要实现一个稍微不同的下标运算符:

const double &LowerTriangular::operator()(unsigned i, unsigned j) const override {
return data_[i*(i + 1)/2 + j];
}

虽然上面的运算符并不完整,因为如果有人要求输入位于对角线右侧(但仍在理论矩阵内)的条目,则会返回另一个(不相关的)元素,但 0应该返回。

因为引用不能绑定(bind)到局部变量,所以我不能只返回 0。那么,我该如何实现呢?

我只能想出一个局部静态变量:

const double &LowerTriangular::operator()(unsigned i, unsigned j) const override {
static const double zero = 0;
if (j > i) return zero;
return data_[i*(i + 1)/2 + j];
}

我可以让函数按值返回,但是非 const 版本呢(当调用者实际需要修改内容时)?如何确保调用者不修改 zero 静态变量?这行得通,但有点难看:

const double &LowerTriangular::operator()(unsigned i, unsigned j) const override {
static double zero = 0;
if (j > i) return zero = 0; // kind of ugly but works
return data_[i*(i + 1)/2 + j];
}

double &LowerTriangular::operator()(unsigned i, unsigned j) override {
return const_cast<double &>( const_cast<const LowerTriangular &>(*this)(i, j) );
}

那么最好的解决方案是什么?

最佳答案

您选择的优化与您提供的界面冲突。

一种方法可能是不返回引用,而是返回一个行为类似于引用的透明包装器。类似于 std::vector::<bool>::reference 的内容.一个例子:

struct Reference {
double* element;

operator double() const {
return element
? *element
: 0;
}
Reference& operator=(double d) {
if (!element)
throw std::out_of_range("Cannot modify right side of diagnoal");
*element = d;
return *this;
}
};

const Reference
LowerTriangular::operator()(unsigned i, unsigned j) const {
return {
j > i
? nullptr
: data_ + i*(i + 1)/2 + j
};
}

Reference
LowerTriangular::operator()(unsigned i, unsigned j) {
return {
j > i
? nullptr
: data_ + i*(i + 1)/2 + j
};
}

这与 std::vector::<bool>::reference 有相同的注意事项,即获取引用的地址不会为您提供指向双对象的指针。这可能是重载 operator& 的少数情况之一。说得通。但这也可能违反直觉,当 API 的用户知道包装器并且确实想要包装器的地址时。

您可以指定尝试修改对角线的右侧是未定义的行为,而不是抛出。

关于c++ - 如何从(通常)返回引用(对成员数据)的成员函数返回常量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55653109/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com