通过引用函数传递新构造的对象是否合法?

Ada*_*eld 16 c++

具体来说,是以下合法的C++?

class A{};

void foo(A*);
void bar(const A&);

int main(void)
{
    foo(&A());  // 1
    bar(A());  // 2
}

它似乎工作正常,但这并不意味着它必然是合法的.是吗?

编辑 - 更改A&const A&

Jam*_*kin 16

1:不允许使用临时地址.Visual C++允许它作为语言扩展(默认情况下语言扩展是打开的).

2:这是完全合法的.

  • 禁止取右值的地址,而不是专门的临时地址。这就是为什么这是被禁止的;`A()` 返回一个右值。 (2认同)
  • @underscore_d True - 我使用非正式术语'临时',更具体地说是一个未命名的临时变量,正如你正确地说的那样,是一个右值.如果我们挑剔,`A()`不会'返回'rvalue(构造函数没有返回值),它是一个prvalue表达式. (2认同)

Mat*_*ice 9

不,将非const引用传递给临时对象是违反标准的.您可以使用const引用:

class A{};

void bar(const A&);

int main(void)
{
    bar(A());  // 2
}
Run Code Online (Sandbox Code Playgroud)

因此,虽然一些编译器会接受它,并且只要在分号后不使用内存就可以工作,但是符合标准的编译器不会接受它.

  • 通过编辑OP,这个答案已经过时了 (4认同)

KTC*_*KTC 6

完全符合标准的C++中不允许使用foo,而bar是可以的.虽然可能性很大,但是foo会在发出警告的情况下进行编译,并且bar可能也可能不会编译并发出警告.

A()创建一个临时对象,除非绑定到引用(如bar中的情况),或用于初始化命名对象,否则在创建它的完整表达式的末尾销毁.创建用于保存引用初始值设定项的临时值会持续到其引用范围的末尾.对于bar的情况,这是函数调用,因此您可以完全安全地使用A inside bar.禁止将临时对象(这是一个右值)绑定到非const引用.同样禁止使用rvalue的地址(作为参数传递给foo初始化A).