C++ 获取临时对象的地址

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2280688/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:51:14  来源:igfitidea点击:

Taking the address of a temporary object

c++rvalue

提问by fredoverflow

§5.3.1 Unary operators, Section 3

§5.3.1 一元运算符,第 3 节

The result of the unary & operator is a pointer to its operand. The operand shall be an lvalueor a qualified-id.

一元 & 运算符的结果是指向其操作数的指针。操作数应为左值或限定 ID。

What exactly does "shall be" mean in this context? Does it mean it's an error to take the address of a temporary? I was just wondering, because g++ only gives me a warning, whereas comeau refuses to compile the following program:

在这种情况下,“将是”究竟是什么意思?这是否意味着获取临时地址是错误的?我只是想知道,因为 g++ 只给了我一个警告,而 comeau 拒绝编译以下程序:

#include <string>

int main()
{
    &std::string("test");
}

g++ warning: taking address of temporary

g++警告taking address of temporary

comeau error: expression must be an lvalue or a function designator

科莫错误expression must be an lvalue or a function designator

Does anyone have a Microsoft compiler or other compilers and can test this program, please?

请问有人有微软编译器或其他编译器可以测试这个程序吗?

采纳答案by AnT

The word "shall" in the standard language means a strict requirement. So, yes, your code is ill-formed (it is an error) because it attempts to apply address-of operator to a non-lvalue.

标准语言中的“应”一词意味着严格的要求。所以,是的,您的代码格式错误(这是一个错误),因为它试图将地址运算符应用于非左值。

However, the problem here is not an attempt of taking address of a temporary. The problem is, again, taking address of a non-lvalue. Temporary object can be lvalue or non-lvalue depending on the expression that produces that temporary or provides access to that temporary. In your case you have std::string("test")- a functional style cast to a non-reference type, which by definition produces a non-lvalue. Hence the error.

但是,这里的问题不是尝试获取临时. 问题再次是获取非左值的地址。临时对象可以是左值或非左值,具体取决于生成该临时对象或提供对该临时对象的访问的表达式。在您的情况下,您有std::string("test")- 将函数样式转换为非引用类型,根据定义,该类型会生成非左值。因此错误。

If you wished to take address of a temporary object, you could have worked around the restriction by doing this, for example

如果您希望获取临时对象的地址,则可以通过执行此操作来解决此限制,例如

const std::string &r = std::string("test");
&r; // this expression produces address of a temporary

whith the resultant pointer remaining valid as long as the temporary exists. There are other ways to legally obtain address of a temporary object. It is just that your specific method happens to be illegal.

只要临时存在,结果指针就保持有效。还有其他合法获取临时对象地址的方法。只是你的具体方法碰巧是非法的。

回答by AnT

When the word "shall" is used in the C++ Standard, it means "must on pain of death" - if an implementation does not obey this, it is faulty.

当 C++ 标准中使用“shall”这个词时,它的意思是“必须忍受死亡的痛苦”——如果一个实现不遵守这个,那就是错误的。

回答by Hans Passant

It is permitted in MSVC with the deprecated /Ze (extensions enabled) option. It was allowed in previous versions of MSVC. It generates a diagnostic with all warnings enabled:

MSVC 中允许使用已弃用的 /Ze(启用扩展)选项。在以前版本的 MSVC 中是允许的。它生成一个诊断并启用所有警告:

warning C4238: nonstandard extension used : class rvalue used as lvalue.

警告 C4238:使用了非标准扩展:类右值用作左值。

Unless the /Za option is used (enforce ANSI compatibility), then:

除非使用 /Za 选项(强制 ANSI 兼容性),否则:

error C2102: '&' requires l-value

错误 C2102:“&”需要左值

回答by James Curran

&std::string("test");is asking for the address of the return value of the function call (we'll ignore as irrelevant the fact that this function is a ctor). It didn't have an address until you assign it to something. Hence it's an error.

&std::string("test");正在询问函数调用的返回值的地址(我们将忽略该函数是一个 ctor 的无关紧要的事实)。在您将其分配给某物之前,它没有地址。因此这是一个错误。

回答by MSalters

The C++ standard is a actually a requirement on conformant C++ implementations. At places it is written to distinguish between code that conformant implementations must accept and code for which conformant implementations must give a diagnostic.

C++ 标准实际上是对符合 C++ 实现的要求。在某些地方编写它是为了区分一致性实现必须接受的代码和一致性实现必须给出诊断的代码。

So, in this particular case, a conformant compiler mustgive a diagnostic if the address of an rvalue is taken. Both compilers do, so they are conformant in this respect.

因此,在这种特殊情况下,如果采用了右值的地址,则符合标准的编译器必须给出诊断信息。两个编译器都这样做,因此它们在这方面是一致的。

The standard does not forbid the generation of an executable if a certain input causes a diagnostic, i.e. warnings are valid diagnostics.

如果某个输入导致诊断,即警告是有效的诊断,则该标准不禁止生成可执行文件。

回答by Hans W

I'm not a standards expert, but it certainly sounds like an error to me. g++ very often only gives a warning for things that are really errors.

我不是标准专家,但这对我来说肯定是个错误。g++ 经常只对真正错误的事情发出警告。

回答by SPapiernik

user defined conversion

用户定义的转换

struct String {
    std::string str;

    operator std::string*() {
        return &str;
    }
};

std::string *my_str = String{"abc"};