这真的是交换两个引用的坏主意。引用不应该是可重置的,所以它不应该是可能的。我知道的很多。
我想做的是交换两个引用,交换两个指针:地址交换但不是数据。假设:
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内的引用被交换。遗憾的是,如果没有相当丑陋的operator =(),它就无法工作。至少它在MSVC中对我有用,不确定g ++是否会接受它(但我想它应该)。
整个引用交换应该在一个对象中使用,该对象是通过对另一个对象内部的引用构造的,并且我想对它们进行swap()函数。我想避免使用指针,因为引用具有很好的非nullarity特性。它也是一个更好的设计(resetable_ref本身除外)。
有没有人更清楚如何去做?任何人都可以想到一些可能遇到的兼容性/未定义的行为问题吗?
我编写了大部分代码而没有编译,如果你注意到一些错字,请耐心等待。
编辑:在我看来,很多人都忽略了问题的关键点。我知道如何使用指针,甚至如何在一个漂亮的模板中包装指针。问题标记为“ hack ”,这就是预期的结果。不要告诉我像“不要这样做,使用指针”这样的东西,因为那不是我问的。如果您不喜欢这个主题,请不要回答,但不要仅因为您使用指针而将问题推回原点。
答案 0 :(得分:3)
一个可变引用是......不再是指针,你需要像引用一样隐式解引用。
template<class T>
class mutable_ref
{
public:
mutable_ref(T& t) :p(&t)
{}
operator T&() { return *p; }
operator const T&() const { return *p; }
void swap(mutable_ref& s)
{ std::swap(p,s.p); }
private:
T* p;
};
// just in case you also want to specialize std::swap for mutable_ref.
// not necessary, since the generic std::swap<T> use twice =, that is available.
namespace std
{
template<class T>
void swap(mutable_ref<T>& a, mutable_ref<T>& b)
{ a.swap(b); }
}
注意缺少默认的ctor,初始化ctor接受引用,这使得该类不可为空。
唯一的问题是,访问最终的T成员,是“。”操作员,不可覆盖,你需要为此目的的东西。
简单的事情是使用*和 - &gt;如...
T* operator->() const { return p; }
T& operator*() const { return *p; }
在mutable_ref
声明 -