非常量引用返回函数在常量值返回函数上用作 r 值

Non-const reference-returning function getting used as r-value over const value-returning function

本文关键字:函数 返回 常量 引用 非常      更新时间:2023-10-16

我有两个版本的函数。一个按值返回,旨在用作 r 值。另一个通过引用返回,旨在用作 l 值(写入audio_data向量(。

float AudioData::sample(unsigned frame, unsigned channel) const
{
return audio_data[frame * channel_count + channel];
}
float& AudioData::sample(unsigned frame, unsigned channel)
{
clearSplits(); // Clear out cached information that may be invalidated by this call
return audio_data[frame * channel_count + channel];
}

在调试时,我注意到引用返回覆盖被用作 r 值:

const float *AudioData::split(unsigned channel)
{
if (splits[channel] != nullptr) return splits[channel];
if (channel_count == 1) return data();
float *split = new float[frame_count];
for (unsigned i = 0; i < frame_count; ++i)
{
split[i] = sample(i, channel); // Calls the reference-returning override
}
splits[channel] = split;
return split;
}
void AudioData::clearSplits() // This gets called while writing to the splits!
{
for (unsigned i = 0; i < splits.size(); ++i)
{
if (splits[i] != nullptr) delete[] splits[i];
splits[i] = nullptr;
}
}

为什么编译器在不修改返回引用时选择使用非 const l 值覆盖,我如何防止它这样做?

重载解析根本不关心函数的返回类型。它所关心的只是调用的参数类型。在您的情况下,由于您从split(一个非 const 限定的函数(调用sample,因此隐式对象参数 (this( 不是 const 限定的。因此,非常量重载被调用,并返回一个引用。

一个简单的解决方案是提供另一个函数,另一个名称,也返回一个副本。

float AudioData::csample(unsigned frame, unsigned channel) const
{
return sample(fram, channel); // will always call the const overload
}

如果您反对这样做,那么您可以随时const_cast调用正确的重载:

split[i] = const_cast<AudioData const *>(this)->sample(i, channel);