使用临时地址安全吗?
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
引用不能。
在我的程序中,我想获取一个临时地址。这是一个例子:
#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
引用不能。