【问题标题】:Are temporary C++ objects lvalues? [duplicate]临时 C++ 对象是左值吗? [复制]
【发布时间】:2019-02-28 15:01:10
【问题描述】:

我对以下代码感到困惑,它(令我惊讶的是)编译:

class A {
  int a=0;
};

A returnsA(void)
{
  static A myA;

  return myA;
}

void works(void)
{
  A anotherA;

  returnsA() = anotherA;
}

我在标准或网络上找不到任何暗示它不应该编译的东西。对我来说,这似乎很奇怪。

我猜returnsA() 正在返回一个对象(myA 的副本),因此我们对其调用默认的复制赋值运算符,anotherA 被复制分配给返回的对象,然后超出范围并被销毁。

我期待的行为更像这样,但无法编译:

int returnsint(void)
{
  static int i=0;

  return i;
}

void doesntwork(void)
{
  int anotherint=0;

  returnsint() = anotherint;
}

谁能进一步告诉我这种行为?

【问题讨论】:

  • 相关?也许是愚蠢的stackoverflow.com/q/51172341/817643
  • @StoryTeller 是的,它使用隐式定义的复制赋值运算符。很合法。
  • @P.W,存储说明符是静态的吗?我返回的是 myA 的副本,而不是 myA 本身,对吗?
  • @P.W 它传递静态对象的副本。它是静态的这一事实并不重要。
  • 我实际上更惊讶于 int 版本不合法而不是 class 版本。 (我原以为 int 版本完全没用但仍然合法)。

标签: c++


【解决方案1】:

对象不是左值或右值。 lvaluervalue 这两个词是表达式类别。它们对表达式进行分类,而不是对象。


对于线路:

returnsA() = anotherA;

由于= 的操作数是类类型,因此会搜索重载的运算符函数。 operator= 的特殊之处在于,如果用户没有显式重载它,则会生成默认重载。该重载是带有签名的成员函数:

A& A::operator=(A const&);

并且调用returnsA() = anotherA; 转换为returnsA().operator=(anotherA);,这是成员运算符重载的基本机制。

表达式returnsA() 具有类别prvalue。但是在纯右值表达式上调用成员函数是完全可以的,所以这里没有问题。


如果您想劝阻您的班级不要接受此类作业,请see here。至于为什么默认赋值运算符不能这样工作,see here

【讨论】:

  • 您的意思是“对象可能是左值或右值?”它们是其中之一。你甚至指出returnsA() 产生了prvalue。
  • @doug 不,我的意思是我说的。对象不是表达式,表达式不是对象。这些是不同的概念。 returnsA() prvalue 表达式(它不会“产生”prvalue)。执行此表达式可能会导致临时对象的具体化,但表达式不是对象,反之亦然。
猜你喜欢
  • 2014-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 2019-06-17
相关资源
最近更新 更多