Why Do We Need std::addressof, If We Already Have The & Operator?

At first glance, the std::addressof method appears to be redundant. Its  output is the address of the object passed to it. It’s exactly what the & operator have been doing ever since C was developed in the early 70’s:

#include <iostream>
#include <memory>

template<typename T>
void getAddress(T t)
{
	assert( std::addressof(t) == &t);
	std::cout << "Address returned by & operator: " << std::ios::hex << &t << "\n";
	std::cout << "Address returned by addressof: " << std::ios::hex << std::addressof(t) << "\n";
}

int main()
{
	int i = 0;
	std::cout << "Getting the address of an int type \n";
	getAddress(i);
}

Getting the address of an int type:
Address returned by & operator: 20480024FC1C
Address returned by addressof: 20480024FC1C

C , however, don’t  allow operator overloading while C++ do. More specifically C++ will let you overload the & operator.  Consider instantiating the getAddress template function with the  Buffer class defined below:

#include <iostream>
#include <memory>

class Buffer
{
private:
	static const size_t buffer_size = 256;
	int bufferId;
	char buffer[buffer_size];

public:
	Buffer(int bufferId_) : bufferId(bufferId_) {}
	Buffer* operator&() { return reinterpret_cast<Buffer*> (&buffer); }  //BAD practice, only for  illustration!
};

template<typename T>
void getAddress(T t)
{
	std::cout << "Address returned by & operator: " << std::ios::hex << &t << "\n";
	std::cout << "Address returned by addressof: " << std::ios::hex << std::addressof(t) << "\n";
}

int main()
{
	Buffer b(1);
	std::cout << "Getting the address of a Buffer type: \n";
	getAddress(b);
}

Getting the address of a Buffer type:
Address returned by & operator: 20480078F50C
Address returned by addressof: 20480078F508

In the Buffer class, the & operator is (badly) overloaded and coerced to return the address of the internal  buffer as the address of the  object. The template implementation expecting a type with an accessible & operator which, it assumes,  returns the address of the object, report the wrong address.  At the same time std::addressof method returns accurately the object’s  address.

So this is why we need std::addressof. It  was introduced into  the boost library and later into the C++ 11 standard as a workaround for a potentially unreliable & operator.

When should you use the std::addressof  method?

You should use std::addressof instead of & in any template implementation taking the address of a user-defined object. Doing so is not a perfect solution as it might  cause unexpected  behavior with types relying on an overloaded & operator (some argue it is an appropriate and just  punishment for developers dabbling in this dark art) .  However, it is possible to  detect the conflict of address reporting and  template expectations in debug builds  with assert( std::addressof(t) == &t) :

template<typename T>
void getAddress(T t)
{
	assert( std::addressof(t) == &t);
	std::cout << "Address returned by & operator: " << std::ios::hex << &t << "\n";
	std::cout << "Address returned by addressof: " << std::ios::hex << std::addressof(t) << "\n";
}

This way you will at least get a heads up while you develop and test your code.

Conclusion

Even prior to C++11 ,  Overloading the & operator has been discouraged, frowned upon  and even prohibited by several C++ coding guidelines such as the one used in aircraft and medical devices software development:   MISRA-C++:2008  (section 5-3-3).  A boost library version of addressof was released in  2002 suggesting that overloading the address operator was perceived as a problem for a long while before the C++ 11 makeover. Yet, the  introduction of the std::addressof  method  into the C++11  standard  is evidence that  the C++ committee  feared too much legacy code will break if the & operator no longer allowed to be overloaded.  I guess this is one case where the jokes about C++ giving you the tools to shoot yourself in the foot are right on the nose.

2 thoughts on “Why Do We Need std::addressof, If We Already Have The & Operator?”

  1. Common sense would be to overload both the & operator and std::addressof so that you wouldn’t get the assertion fail.

  2. Overloading both std::addressof and & It would prevent getting the assertion but will miss the point of having std::addressof in the first place. std::addressof was added as a workaround to ensure there was another (independent) way to get the true address of an object. So having std::addressof report an inaccurate address (or alternatively not using any assert) is similar to shutting down a smoke detector so we can be sure we won’t be hearing that annoying noise when there is a fire in the house 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *