在我的节目中,我想取一个临时的地址。这是一个例子:
#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
标志。
以下是我的问题:安全和可靠?在什么情况下会出现问题?
答案 0 :(得分:13)
如果你的定义是'安全可靠的&#34;包括&#34;如果编译器更新,将编译并生成相同的结果&#34;那么你的例子是无效的。
你的例子在所有C ++标准中都是不正确的。
这意味着,即使编译器现在可以强制接受它,也不能保证编译器的未来更新会接受它,或者如果编译器确实接受了代码,则会产生相同的预期效果。< / p>
大多数编译器供应商都有支持编译器中非标准功能的形式,并在编译器的后续版本中删除或改变对这些功能的支持。
考虑更改您的函数,使其接受const Number &
而不是指针。 const
引用可以隐式绑定到临时引用,而不需要将编译器强制转换为提交(例如,使用命令行选项)。非const
引用不能。
答案 1 :(得分:8)
&Number(456)
是一个错误,因为内置的&
运算符无法应用于右值。由于这是一个错误,它既不安全也不可靠。 &#34;可能出现什么问题&#34;是因为遵循C ++标准的编译器可能会拒绝代码和/或意外行为。您依赖于您的编译器支持一些C ++ - 就像定义此代码的方言一样。
您可以通过各种方式输出临时对象的地址。例如,添加成员函数auto operator&() { return this; }
。重载的operator&
可以应用于类类型的prvalues。
另一种方法是拥有一个与move
相反的函数:
template<typename T>
T& make_lvalue(T&& n)
{
return n;
}
然后你可以print(&make_lvalue(Number(456)));
如果您感觉不好,可以使operator&
的全局模板重载。
答案 2 :(得分:-4)
这很好但是..
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
}
你会删除“&amp;”来自您的代码:
Number example(123);
print(example);
print(Number(456));
如果你需要传递一个指针,你只需要用“*”取消引用它。
chasester