取一个临时的地址是否安全?

时间:2018-04-07 00:35:07

标签: c++ pointers memory-address

在我的节目中,我想取一个临时的地址。这是一个例子:

#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标志。

以下是我的问题:安全可靠?在什么情况下会出现问题?

3 个答案:

答案 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