代码之家  ›  专栏  ›  技术社区  ›  Evan Teran

临时奇数的常量引用

  •  7
  • Evan Teran  · 技术社区  · 16 年前

    我们都知道这样的事情在c++中是有效的:

    const T &x = T();
    

    而:

    T &x = T();
    

    a recent question 谈话引出了这条规则。行动组贴出了一些代码,很明显引起了UB的注意。但我希望它的一个修改版本可以工作(这是修改后的版本):

    #include <iostream>
    using namespace std;
    
    class A {
    public:
        A(int k) { _k = k; };
        int get() const { return _k; };
        int _k;
    };
    
    class B {
    public:
        B(const A& a) : _a(a) {}
        void b() { cout << _a.get(); }
        const A& _a;
    };
    
    B* f() {
        return new B(A(10));
    }
    
    int main() {
        f()->b();
    }
    

    在一些机器上打印垃圾,在其他机器上打印10。。。听起来像是乌布:-)。但后来我想 A int 它所做的一切都是初始化一个并读取它。为什么不直接打电话 A 内景

    #include <iostream>
    using namespace std;
    
    typedef int A;
    
    class B {
    public:
        B(const A& a) : _a(a) {}
        void b() { cout << _a; }
        const A& _a;
    };
    
    B* f() {
        return new B(A(10));
    }
    
    int main() {
        f()->b();
    }
    

    它打印出来了 10 每一次。至少是这样 似乎 就像常量引用规则对 版本,但不适用于类版本。它们都是由于堆的使用而导致的吗?我只是运气好吗 内景 因为编译已经看穿了所有 const ? 我遗漏了规则的哪一方面?

    3 回复  |  直到 9 年前
        1
  •  19
  •   AnT stands with Russia    16 年前

    它只是演示了通过“在编译器中尝试”来分析语言行为通常不会产生任何有用的结果。由于同样的原因,你的两个例子都是无效的。

    尝试将临时变量作为构造函数的参数传递并在构造函数内附加const引用将不会建立上述链接,也不会延长临时变量的生存期。

    此外,按照C++标准,如果你这样做

    struct S {
      const int &r;
    
      S() : r(5) {
        cout << r; // OK
      }
    };
    

    S s;
    cout << s.r; // Invalid
    

    无效。

    你的实验 int 只是“看起来有用”,纯属偶然。

        2
  •  3
  •   fredoverflow    16 年前

    void b() {
        int i = rand();
        int j = rand();
        cout << _a << endl;
    }
    

    打印出随机数。

        3
  •  3
  •   fredoverflow    16 年前

    每次打印10张。

    稍微修改一下main函数,它就不会再打印10了:

    int main()
    {
        B* p = f();
        cout << "C++\n";   // prints C++
        p->b();            // prints 4077568
    }
    

    这种联系是如何在什么层次上建立起来的?

    见12.2[临时类]§4和§5:

    有两种情况下,临时销毁在不同的点比结束的充分表达。 第一个上下文是[…]

    在函数调用中临时绑定到引用参数的操作将一直持续到包含该调用的完整表达式完成为止。

    所以在你的情况下,临时的是销毁后的评估充分表达 new B(A(10))

    推荐文章