c++临时函数和构造函数
C++ temporaries and constructors
为什么有些编译器抱怨从构造函数中获取临时对象的地址,而有些则没有?
例如:WriteLine(&String8("Exception"));
我假设抱怨的编译器没有将该地址存储在堆栈上,如果我忽略警告,它将爆炸。有没有办法让它在一行中工作?最好的/唯一的方法是一个静态方法上的类,返回一个地址?嗯,我不认为String8类上的静态方法返回一个指针会工作,因为它会保存String8类到一个寄存器,然后在WriteLine()
您给出的示例代码,
WriteLine(&String8("Exception"));
是无效的作为标准c++,除非String8
类型定义了自定义的地址操作符。
你问
,
”
为什么有些编译器会抱怨从构造函数中获取临时对象的地址,而有些则不会?
有些编译器会抱怨,因为c++标准规定不能使用内置地址操作符来获取临时对象的地址:
c++ 11§5.3.1/3 :
一元&
操作符的结果是指向其操作数的指针。操作数应为左值或限定id。”
一些编译器,如Visual c++,没有抱怨,因为它们提供了将地址作为语言扩展的能力。
注意,用户自定义类型可以定义自定义地址操作符。因此,在您的情况下,它取决于String8
类型。
你进一步问,
“有没有办法让它在一行中工作?
是的,可以定义地址操作符。但这不是个好主意。首先,它只会给标准库等带来问题,其次,这样做的需求非常少。
我只记得一个我认真考虑过这种解决方案的情况,即传递一个COM智能指针作为输出参数。我没有定义地址操作符,而是定义了命名方法。它更清晰,而且不会干扰其他东西。
代码完全有效(在MSVC上)。你可以忽略这个警告,把它当作转移注意力的话题。
有两个问题需要考虑:
- 获取临时(a.k.)的地址。a: rvalue),根据标准& 是不允许的。
- 占用临时用户地址的生存时间。
Counter Issue 1:
MSVC允许您通过扩展获取临时地址。因此,获取临时地址将至少在您的情况下编译(由MSVC提供)。
Counter Issue 2:
此外,还保证临时String8("Exception")
至少在表达式结束之前有效。注意,表达式结束于WriteLine()
的返回值之后,确切地说是;
( call结尾的分号)。所以它是完全有效的。在这种情况下,您可以将警告视为转移注意力。
c++ 03 Standard§12.2/3:
临时对象在(词法上)包含创建它们的点的完整表达式(1.9)求值的最后一步被销毁。
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 构造函数/函数声明参数列表中的统一初始化
- 在c++中为链接列表创建复制构造函数/函数
- 如何声明模板函数,以便可以在类构造函数/函数中传递
- 在C 中,如何调用构造函数函数
- 在C++中构造模板函数时出现编译错误 C2664 和 C2440
- Rcpp:构造模板函数
- 采用nulltpr_t的构造函数:函数定义不声明参数
- 使用基于模板的构造函数构造std::函数
- 构造函数:函数不接受3个参数
- 就地构造 std::函数目标
- 将字符串构造作为函数参数传递
- C++:从模板化方法构造std::函数
- 构造std::函数的向量时出现编译器错误
- 构造<stl_hashtable>函数参数是否在
- libstdc++和libc++在用lambda构造std::函数时的不同行为
- 编译器构造-带有函数的类的c++sizeof()
- 使用 c++11 构造映射函数
- 调用构造与函数原型混淆
- 在不调用initializer_list构造函数的情况下,将不可复制、不可移动的类型构造为函数形参