使用临时地址安全吗?

Is it safe to take the address of a temporary?

在我的程序中,我想获取一个临时地址。这是一个例子:

#include <iostream>

struct Number {
    int value;
    Number(int n) {
        value = n;
    }
};

void print(Number *number) {
    std::cout << number->value << std::endl;
}

int main() {
    Number example(123);
    print(&example);
    print(&Number(456)); // Is this safe and reliable?
}

这将输出:

123
456

要编译,需要 -fpermissive 标志。

我的问题是:安全可靠吗?在什么情况下可能会出错?

这很好但是..

Number *a;
print(a); // this would be a null ptr error

我会如何改变它

void print(const Number num) // make the paramater const so it doesnt change
{
   std::cout << num.value << std::endl; // note the . instead of -> cuz this is a reference not a pointer
}

您可以从您的代码中删除“&”,例如:

Number example(123);
print(example);
print(Number(456));

如果你需要传递一个指针,你只需放一个“*”来取消引用它。

追逐者

&Number(456) 是一个错误,因为 built-in & 运算符不能应用于右值。既然是错误,那么既不安全也不可靠。 "What could go wrong" 是代码可能会被遵循 C++ 标准的编译器拒绝 and/or 行为异常。您依赖于您的编译器支持定义此代码的某些类似 C++ 的方言。


您可以通过多种方式输出临时对象的地址。例如添加一个成员函数 auto operator&() { return this; } 。重载 operator& 可以应用于 class 类型的纯右值。

另一种方法是使用与 move 相反的函数:

template<typename T>
T& make_lvalue(T&& n)
{
     return n;
}

然后你可以print(&make_lvalue(Number(456)));

如果你心情不好,你可以重载 operator&.

的全局模板

如果您对 "safe and reliable" 的定义包括 "will compile and produce the same results if the compiler is updated" 那么您的示例无效。

您的示例在所有 C++ 标准中都是 ill-formed。

这意味着,即使现在可以强制编译器接受它,也不能保证您的编译器的未来更新会接受它,或者即使编译器确实接受了代码,也会产生相同的预期效果.

大多数编译器供应商都有形式支持编译器中的 non-standard 功能,并在编译器的更高版本中删除或更改对这些功能的支持。

考虑更改您的函数,使其接受 const Number & 而不是指针。 const 引用可以隐式绑定到临时对象,而无需强制编译器提交(例如使用命令行选项)。非 const 引用不能。