这实际上是交换两个参考的坏主意。引用不应该是可重置的,因此它不应该是可能的。我知道的就这么多。
我想要做的是交换两个引用,以一种交换两个指针的方式:交换地址但不交换数据。认为:
int a = 0, b = 1;
int *pA = &a, *pB = &b;
std::swap(pA, pB);
现在 *pA 为 1 且 *pB 为 0,但 a 仍为 0 且 b 仍为 1。但是,这对于引用是不可能的:
int a = 0, b = 1;
int &rA = a, &rB = b;
std::swap(pA, pB);
现在交换了引用,但也交换了原始值。我唯一能想到的是:
template <class _Ty>
struct resetable_ref {
_Ty &ref;
inline resetable_ref(resetable_ref &r)
:ref(r.ref)
{}
inline resetable_ref(_Ty &_ref)
:ref(_ref)
{}
inline resetable_ref &operator =(resetable_ref &r)
{
if(sizeof(resetable_ref) == sizeof(void*)) // compile-time constant (true)
*reinterpret_cast<void**>(this) = *reinterpret_cast<void**>(&r);
else
memcpy(this, &r, sizeof(resetable_ref)); // optimized away as dead code
return *this;
}
inline operator _Ty &()
{
return ref;
}
};
int a = 0, b = 1;
resetable_ref<int> rrA(a), rrB(b);
std::swap(rrA, rrB);
现在 a 仍然是 0 而 b 仍然是 1,并且 rrA 和 rrB 内部的引用被交换了。遗憾的是,如果没有相当丑陋的运算符 =(),它就无法工作。至少它在 MSVC 中对我有用,不确定 g++ 是否会接受它(但我想它应该)。
整个引用交换应该用于一个对象,该对象是通过对内部另一个对象的引用构造的,我想在它们上创建一个 swap() 函数。我想避免使用指针,因为引用的非空值特性很好。它也将是一个更好的设计(resetable_ref 本身除外)。
有没有人对如何去做有更好的想法?谁能想到一些可能遇到的兼容性/未定义的行为问题?
我写了大部分代码没有编译,如果你发现一些错别字,请多多包涵。
编辑:在我看来,很多人都忽略了问题的重点。我知道如何使用指针,甚至知道如何将指针包装在一个漂亮的模板中。这个问题被标记为“ hack ”,这是预期的。不要告诉我诸如“不要这样做,使用指针”之类的东西,因为那不是我所要求的。如果您不喜欢该主题,请不要回答,但不要仅仅因为您会使用指针而对问题投反对票。