m0_75091674 2025-12-08 18:02 采纳率: 0%
浏览 8

C++为什么临时对象能够赋值给引用?

下面这段C++代码能够在VS2008里面编译通过。

class A{};

int main(){
    A& a_ref = A(); 
    return 0;
}

我认为A()是一个临时对象,不能够用来初始化non-const的对象。

可这段代码在VS2008里面能够编译通过,为什么呢?

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-12-08 18:04
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    你提出的问题非常有代表性,涉及到 C++ 中 临时对象(temporary object)引用(reference) 之间的关系。我们来详细分析一下这段代码为什么在 VS2008 中能通过编译,以及其背后的原理。


    ✅ 问题核心:

    你写的代码是:

    class A {};
    
    int main() {
        A& a_ref = A(); 
        return 0;
    }
    

    你认为 A() 是一个临时对象,不能用来初始化非 const 引用(non-const reference),但该代码却在 VS2008 中编译通过。


    🧠 为什么可以?

    1. C++ 标准中允许临时对象绑定到 non-const 引用

    虽然通常我们会认为临时对象只能绑定到 const 引用const A&),但在某些情况下,临时对象也可以绑定到 non-const 引用

    例如,在以下代码中:

    A& a_ref = A();
    

    这个语句实际上是将一个临时对象 A() 绑定到一个 non-const 引用 a_ref

    这在 C++98/03 标准中是允许的,尽管有些编译器会发出警告(如 MSVC 在某些版本中会警告)。


    2. VS2008 的行为是符合 C++98 标准的

    VS2008 是基于 C++98 标准实现的,因此它支持这种语法。

    注意: 在 C++11 及之后的标准中,临时对象不能直接绑定到 non-const 引用。如果你尝试这样做,编译器会报错。


    ⚠️ 为什么会有争议?

    这个问题在 C++ 社区中存在一定的争议,原因如下:

    • 临时对象是 短暂存在的,如果将其绑定到 non-const 引用,可能会导致后续对引用的修改被忽略或造成未定义行为。

    • 例如:

      A& a_ref = A();
      a_ref.some_method(); // 这个调用可能不会有任何实际效果,因为临时对象已经销毁
      

    ✅ 解决方案与建议

    🔧 1. 使用 const 引用(推荐方式)

    为了安全和可维护性,建议使用 const A& 来绑定临时对象:

    const A& a_ref = A();
    

    这样可以避免潜在的未定义行为,并且符合现代 C++ 的最佳实践。


    🔧 2. 创建具名对象(更清晰的方式)

    如果你需要操作对象,而不是仅仅引用它,最好创建一个具名对象:

    A a;
    A& a_ref = a;
    

    这样更直观、更安全。


    🔧 3. 如果你需要修改临时对象(不推荐)

    你可以使用 std::move 来“转移”临时对象的所有权(仅适用于具有移动语义的类):

    A&& a_ref = std::move(A());
    

    但这并不常见,也不推荐用于一般用途。


    📌 总结

    | 问题 | 原因 | |------|------| | 为什么 A& a_ref = A(); 能通过? | 在 C++98/03 标准中,临时对象可以绑定到 non-const 引用,尽管这是不推荐的做法。 | | VS2008 为什么能编译? | VS2008 是基于 C++98 实现的,所以支持这种语法。 | | C++11 及以后是否支持? | 不支持。C++11 开始禁止临时对象绑定到 non-const 引用。 | | 推荐做法是什么? | 使用 const A& 或创建具名对象。 |


    📝 修改后的代码示例(推荐)

    class A {};
    
    int main() {
        const A& a_ref = A(); // 推荐方式:使用 const 引用
        return 0;
    }
    

    或者:

    class A {};
    
    int main() {
        A a;
        A& a_ref = a; // 更清晰的写法
        return 0;
    }
    

    📚 参考资料


    如有更多关于 C++ 引用、临时对象、生命周期等方面的问题,欢迎继续提问!

    评论

报告相同问题?

问题事件

  • 创建了问题 12月8日