【问题标题】:initialize a non-const reference by a temporary variable [duplicate]通过临时变量初始化非常量引用
【发布时间】:2015-08-04 04:41:42
【问题描述】:

我在尝试对对象使用 C++ 引用时遇到以下错误。在引用this question 之后,我了解到这是因为A() 返回一个临时变量,根据设计,不允许non-const reference 引用该变量。但是,我仍然很好奇为什么 C++ 是这样设计的。为什么A& ra2 = A(); 不能作为A a1 = A(); A& ra1 = a1; 的简写?众所周知,MSVC 通过扩展支持这种语法,但其他实现中不包含该语法。这种速记有什么特别的缺点吗?

class A {
    public:
        int a = 0;
};

int main()
{
    A a1 = A();
    A& ra1 = a1;  //okay
    A& ra2 = A(); //error: invalid initialization of non-const reference of type ‘A&’ from an rvalue of type ‘A’
    return 0;
}

【问题讨论】:

  • duckduckgo.com/… -- 你应该先做一些研究。
  • @UlrichEckhardt 我想我知道错误消息的含义以及它发生的原因。我不是在问如何编写正确的代码,而是我的问题更多是关于这里的语义差异是什么。因为ra1ra2 在语义上具有基本相同的净效果。那么 C++ 不允许第二种初始化方式有什么意义呢?
  • @bl4ck5un 所以。 . .你想要一个“do what I mean”编译器吗?
  • @imallett 我说的是 C++ 作为一种编程语言的设计。
  • 这与移动语义无关。 “用移动语义分配”甚至没有意义。

标签: c++ reference


【解决方案1】:

排队

A& ra2 = A(); 

= 运算符的右侧计算为一个临时对象。您只能使用 const& 来引用临时对象。

线

A& ra1 = a1;  //okay

工作因为a1 不是临时对象,也不是const 对象。

【讨论】:

  • 请查看我的问题更新。
  • @bl4ck5un,我不清楚为什么您认为对a1 的引用和对A() 的引用在语义上是相同的。你知道这对你意味着什么,但我不清楚这个想法。
  • @R Sahu 首先,让我们暂时忘记当前的 C++ 规范,并考虑对 C++ 的可能改进。话虽这么说,ra2,我显然打算引用A() 的对象,而不是临时变量,因为它没有意义。所以问题是,为什么C++不是按照我刚才解释的方式设计的。我相信有一些很好的理由(植根于 PL 理论),那是什么?
  • @bl4ck5un,我恐怕不知道 C++ 进化到这样的深度。
  • @bl4ck5un 确实有道理。你请求一个临时对象,你得到一个临时对象。 (从技术上讲,临时变量不是变量)。如果您不想要临时对象,请不要写 A()A() 明确指定您想要一个临时的 .
【解决方案2】:
A& ra2 = A();

ra2 试图引用一个临时变量。并且更改该临时变量没有任何意义。所以,编译器禁止你做任何废话。

【讨论】:

  • 这确实有些道理,他们后来添加了A&& ra2 = A();
  • 我同意更改临时变量是没有意义的。为什么编译器不直接将A& ra2 = A(); 编译为第一种初始化方式。有什么伤害吗?
  • @MattMcNabb 我的意思是编译器不进行优化是否有特殊原因?
  • MSVC 曾经有过这样的扩展。我不会称之为优化
【解决方案3】:

将引用视为具有编译时检查和潜在更少开销的精美指针。

A& ra2 = A();

这说:

  1. 让我成为A 类型的临时对象。
  2. 销毁该临时对象。
  3. 创建一个指向不存在的临时对象的“指针”。

这是检查进入的地方。编译器意识到这没有意义,并告诉你。

你可能对类似的语法感到困惑:

A my_a = A();

但是,这个例子完全不同。它说:

  1. 让我成为A 类型的临时对象。
  2. 复制该临时对象到my_a(调用my_a的复制构造函数)
  3. 删除临时对象

【讨论】:

  • 对不起,但如果代码被调整为使用const,它会改变结果,但你的答案并没有解释 at all.
  • @UlrichEckhardt 对临时对象的 const 引用是一个缺陷,它破坏了我上面描述的直观语法——而且 SO 也是关于教授最佳实践和事实的。由于 OP 没有询问为什么要编译 const 引用(并且因为 s?he 显然是新手),所以我没有提到它。¶ 但是,正如您在上面的评论中一样,这显然是重复的,我可能不应该费心回答它。 This答案更好。
  • 你的前 1,2,3 完全错误
  • @MattMcNabb 因为一开始是无效的 C++,我想这是不言而喻的。但是,如果您愿意,我会欢迎您的澄清。
  • @imallett 是的,它是无效的 C++,所以没有临时制作或销毁。没有根据说如果此代码是合法的,临时代码将不会延长其生命周期。这段代码不合法​​的原因(如果有的话)不是因为它会产生悬空引用,因为它不会。如果允许此代码,那么我很有信心地说它会被指定来延长临时的生命周期。当然A&& ra2 = A(); 确实扩展了。
猜你喜欢
  • 1970-01-01
  • 2021-04-22
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多