c++中交换两个引用的一种方法

A way to swap two references in C++

本文关键字:一种 方法 引用 两个 c++ 交换      更新时间:2023-10-16

交换两个引用确实是一个坏主意。引用不应该是可重置的,所以它不应该是可能的。我就知道这么多。

我想做的是交换两个引用,就像交换两个指针一样:地址被交换不是数据。假设:

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本身)。

有没有人有更好的办法?有人能想到一些兼容性/未定义的行为问题,可能会遇到这个?

我写的大部分代码没有编译,如果你注意到一些拼写错误,请原谅我。

EDIT:在我看来,很多人都没有抓住问题的关键。我知道如何使用指针,甚至知道如何在一个漂亮的模板中包装指针。问题被标记为"hack",这是预期的结果。不要告诉我诸如"不要这样做,使用指针"之类的东西,因为这不是我要求的。如果你不喜欢这个话题,不要回答,但不要因为你会使用指针而给问题投反对票。

一个可变引用是…不过是一个指针,需要像引用那样进行隐式解引用。

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成员,作为"。"操作符,不可重写,您需要其他东西来实现此目的。

最简单的就是使用*和->作为…

T* operator->() const { return p; }
T& operator*() const { return *p; }

mutable_ref声明中定义-

相关文章: