重载一元运算符 &

18

考虑一个重载了一元运算符 &(取地址)的类。假设这个类是A类。

template <class C>
class A
{
public:
    C * operator &()
    {
        return &data;
    }
    //...
private:
    C data;
}

现在我想要将类型为A的指针传递给某个函数,以填充它的data。我们将其称为f

void f(A * auto_containter)
{
    //...
}

但是很明显下面的代码不会工作(甚至无法编译)。这是因为调用了重载运算符。

A a;
f(&a);

问题如下:

是否有语法可以将 a 的地址传递给 f?如果没有,那么对我来说很奇怪的是为什么允许重载一元运算符 &,因为它会使代码更加容易出错和难以理解。或者还有其他原因吗?


1
滥用运算符重载会使代码更难解码(因此更难理解)。像所有提供的工具一样,不要滥用它们。 - Martin York
你要求“语法”,所以这不是一个答案,但你可以编写 A * A :: addressof() {return this;} - Ben Jackson
6个回答

18

有没有语法可以将 a 的地址传递给 f

是的,有一种丑陋的语法:

f( reinterpret_cast<A*>( &reinterpret_cast<char&>(a) ) );

boost::addressof是一个优秀的通用封装器。


有人能解释一下这段代码吗?特别是reinterpret_cast<char&>(a)。在底层到底发生了什么? - undefined

14

使用 std::addressof 函数(或者在 C++11 之前使用 boost::addressof)来获取地址。无论如何,重载一元运算符 & 是非常可疑的,为什么不使用一个命名函数来返回数据的地址呢?


3
我同意这是可疑的,甚至可能是标准中的一个错误,因为对象的地址是比用于获取它的运算符更基本的概念,这就是为什么每种类型默认都可以使用 operator&,而不像 operator+ 那样。但是对于“为什么要这样做”的经典答案是说,“我不想使用命名函数,因为我想编写通用代码,可以使用地址并与 int 一起工作,但是当这个类在那个通用代码中使用时,我希望它使用另一个地址”。所以解释一下为什么这是一个错误,我们就完成了;-) - Steve Jessop
4
例如,您可以更改通用代码,使用类型特征模板来获取地址,而不是一元运算符&。 - Steve Jessop
7
这个功能在C++11中被加入,被称为std::addressof() - Hugues

4

有没有语法可以将a的地址传递给f?

其他人已经指出了boost::addressof。它所依赖的机制是一个标准保证,使用内置的地址运算符进行reinterpret_cast到引用类型。Boost函数只是包装了相当冗长和笨拙的转换组合。

如果没有,那么对我来说很奇怪,为什么允许重载一元运算符&, 因为这会使代码更加错误和难以理解。还是有其他原因?

在某些情况下,可能更方便。例如,智能指针类可能会提供自定义地址运算符,以便支持将&p写为T**形式参数的实际参数。然而,我认为现在通常认为这不是一个好主意。

祝好运。


2

你为什么要重载一元运算符 & 呢?

除此之外,还有 boost::addressof


在我看来:如果能够使用std::reference_wrapper http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper 重载operator&并返回_ptr,那将非常有用。不幸的是,这一点没有被实现,导致用户代码不如可能的通用。 - alfC

1

1

你所描述的情况很少出现,因为任何编写该函数的人都会采用引用而不是指针。另外,你忘记使用示例类型对A进行实例化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接