【问题标题】:Non-const reference-returning function getting used as r-value over const value-returning function非常量引用返回函数被用作 r 值而不是 const 值返回函数
【发布时间】:2019-10-11 22:40:22
【问题描述】:

我有两个版本的函数。一个按值返回,旨在用作 r 值。另一个通过引用返回,旨在用作左值(写入 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;
    }
}

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

【问题讨论】:

标签: c++ reference


【解决方案1】:

重载解析根本不关心函数的返回类型。它只关心调用的参数类型。在您的情况下,由于您从 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);

【讨论】:

  • 谢谢。我知道在重载之间进行选择时不会考虑返回值,但我不知道在比较 const-ness 时唯一考虑的是调用函数的 const-ness。
  • @Ott 不看调用函数的constness。它查看调用其方法的对象的常量,即“this”(基本上是被调用函数的“参数零”)。这反过来又受“split”的常量影响,因为它与“sample”是同一类的成员,所以对象恰好是相同的。非成员不能是 const 限定的。
猜你喜欢
  • 2020-07-06
  • 2021-08-10
  • 2013-06-08
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多