关于c ++:通过引用函数传递新构造的对象是否合法?

关于c ++:通过引用函数传递新构造的对象是否合法?

Is it legal to pass a newly constructed object by reference to a function?

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

1
2
3
4
5
6
7
8
9
10
class A{};

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

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

它似乎可以正常工作,但这并不意味着它一定合法。 是吗?

编辑-将A&更改为const A&


1:不允许使用临时地址。 Visual C ++允许它作为语言扩展(默认情况下,语言扩展处于启用状态)。

2:这是完全合法的。


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

1
2
3
4
5
6
7
8
class A{};

void bar(const A&);

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

因此,尽管有些编译器会接受它,并且只要不使用分号后的内存,它就可以工作,而合规的编译器将不会接受它。


在完全符合标准的C ++中不允许foo,而bar可以。尽管有机会,但foo会带有警告编译,而bar也可能会或可能不会带有警告编译。

A()创建一个临时对象,除非绑定到引用(如bar所示)或用于初始化命名对象,否则它将在创建该对象的完整表达式的末尾销毁。为保存参考初始化程序而创建的临时目录将一直保留到其参考范围的末尾。对于bar来说,这就是函数调用,因此您可以完美安全地使用A内部bar。禁止将临时对象(是右值)绑定到非常量引用。同样,也禁止使用右值的地址(作为参数传递以初始化foo的A)。


简短的回答是。

如果通过函数将对象作为const引用参数接收-如已修改bar(const A&)方法,则完全合法。该函数可以在该对象上操作,但是在函数调用之后该对象将被销毁(可以使用临时地址,但在函数调用之后不得存储和使用该地址-请参见下文的原因)。

foo(A*)也是合法的,因为临时对象在全表达式结束时被销毁。但是,大多数编译器都会发出有关获取临时地址的警告。

bar(A&)的原始版本不得编译,这是从临时初始化非常量引用的标准。

C++ standard chapter 12.2

3 [...] Temporary objects are destroyed as the last step in evaluating the fullexpression (1.9) that (lexically) contains the point where they were created. [...]

4 There are two contexts in which temporaries are destroyed at a different point than the end of the fullexpression. The first context is when an expression appears as an initializer for a declarator defining an object. In that context, the temporary that holds the result of the expression shall persist until the object’s initialization is complete. [...]

5 The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object to a subobject of which the temporary is bound persists for the lifetime of the reference except as specified below. A temporary bound to a reference member in a constructor’s ctorinitializer (12.6.2) persists until the constructor exits. A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call.
A temporary bound to the returned value in a function return statement (6.6.3) persists until the function exits.

全表达式是不是另一个表达式的子表达式的表达式。


那些A对象将仅存在,直到执行到达分号为止。因此,调用是安全的,但不要尝试保存指针并在以后使用它。另外,编译器可能要求bar接受const引用。


看起来它可能会起作用,但是它没有使用带有Wall选项的g ++进行编译,这是我得到的:

1
2
3
4
5
6
7
michael@hardy-lenovo:~/Desktop$ g++ -Wall a.cpp
a.cpp: In function ‘int main():michael@hardy-lenovo:~/Desktop$ g++ -Wall a.cpp
a.cpp: In function ‘int main():
a.cpp:8: warning: taking address of temporary
a.cpp:9: error: invalid initialization of non-const reference of type ‘A&’ from a temporary of type ‘A’
a.cpp:4: error: in passing argument 1 of ‘void bar(A&)
michael@hardy-lenovo:~/Desktop$

看起来您将需要使用常量引用。


对于// 2,您需要一个const引用

对于/ / 1我认为这是合法的,但没用


是合法的我们有时会使用它来提供一个我们可能要忽略的默认值。

1
2
3
int dosomething(error_code& _e = ignore_errorcode()) {
    //do something
}

在上述情况下,如果没有error_code传递给函数,它将构造一个空的错误代码对象。


完全合法。

该对象将在函数调用期间存在于堆栈中,就像其他任何局部变量一样。


推荐阅读

    excel怎么用乘法函数

    excel怎么用乘法函数,乘法,函数,哪个,excel乘法函数怎么用?1、首先用鼠标选中要计算的单元格。2、然后选中单元格后点击左上方工具栏的fx公

    excel中乘法函数是什么?

    excel中乘法函数是什么?,乘法,函数,什么,打开表格,在C1单元格中输入“=A1*B1”乘法公式。以此类推到多个单元。1、A1*B1=C1的Excel乘法公式

    标准差excel用什么函数?

    标准差excel用什么函数?,函数,标准,什么,在数据单元格的下方输入l标准差公式函数公式“=STDEVPA(C2:C6)”。按下回车,求出标准公差值。详细

    16天的最新的内存引用:4gb上涨10元

    16天的最新的内存引用:4gb上涨10元,,内存价格上涨到4GB 10元 在今天中关村的现货市场,内存价格总体呈发展趋势,但它是小的。内存市场昨日下

    excel常用函数都有哪些?

    excel常用函数都有哪些?,函数,哪些,常用,1、SUM函数:SUM函数的作用是求和。函数公式为=sum()例如:统计一个单元格区域:=sum(A1:A10)  统计多个

    wps如何生成引用

    wps如何生成引用,WPS教程,1.wps怎么添加引用文献wps添加引用文献:1、打开文档,点击WPS文字右侧下拉菜单。2、打开插入>引用>脚注与尾注3、选

    Python之可迭代对象、迭代器、生成器

    Python之可迭代对象、迭代器、生成器,迭代,生成器,一、概念描述可迭代对象就是可以迭代的对象,我们可以通过内置的iter函数获取其迭代器,可

    应用程序对象

    应用程序对象,,应用程序对象是一个应用程序级对象,用于在所有用户之间共享信息,并且在Web应用程序运行期间可以保存数据。 应用的性质: 方法