首页 > 解决方案 > const 引用作为类的成员不一致

问题描述

如果创建一个对临时对象的 const 引用,它的寿命就会延长,就像引用在堆栈中的位置一样。这是该语言的一个很好的特性,尽管它有时会像其他规则的例外一样出现。 https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

但是,当 const 引用是类成员的一部分时,这不起作用。这是语言不一致吗?

示例代码:

int f(int a){return a + 5;}
int main(){
    int const& b = f(2);
    assert(b == 7); // ok, not a dangling reference

    struct single{
        int const& m_;
        single(int const& m) : m_(m){}
    };
    single s{f(3)};
    assert(s.m_ == 8); // fails, dangling reference

    struct pair{
        int const& m1_;
        int const& m2_;
        pair(int const& m1, int const& m2) : m1_(m1), m2_(m2){}
    };

    pair p{f(3), f(4)};
    assert( p.m1_ == 8 ); // fails, dangling reference
}

是否有一种解决方法可以使其工作或至少表现得更一致?

我发现这在现在的一些情况下是一个限制因素。例如,List using with references,在用作成员时更改行为https://stackoverflow.com/a/51878764/225186


EDIT1:在其他类似问题的答案中提到,问题在于构造函数采用了const&规则不适用的地方。然而,一个完美的前锋仍然失败。在这种情况下,要么语言的不一致更加明显,要么完美的前锋不那么完美。

struct single{
    int const& m_;
    template<class T>
    single(T&& m) : m_(std::forward<T>(m)){}
};

EDIT2:声明single const& s{f(3)};仍然无济于事。但是,将常量“移动”到结构会有所帮助。

struct single{
    int m_; // no const!
    template<class T>
    single(T&& m) : m_(std::forward<T>(m)){}
};
...
single const& s{f(3)}; // const ref with extended lifetime

因此,将常量转移到整个结构也许是一种好习惯。

我仍然认为参考成员在语言中的行为很奇怪。https://www.youtube.com/watch?v=uYDt1gCDxhM


EDIT3:正如@Oliv 提到的,如果使用聚合初始化,情况会有所改善。然而,这是相当有限的。

struct single{
    int const& m_;
};
...
single s{f(3)};
assert(s.m_ == 5);

标签: c++c++11const-correctnessdangling-pointerconst-reference

解决方案


推荐阅读