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

标签 c++ pointers reference

<分区>

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

我想做的是交换两个引用,以一种交换两个指针的方式:交换地址不交换数据。假设:

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() 函数。我想避免使用指针,因为引用具有很好的非 nullarity 特性。这也是一个更好的设计(除了 resetable_ref 本身)。

有没有人知道如何去做?谁能想到一些可能会遇到的兼容性/未定义行为问题?

我写了大部分代码没有编译,如果你发现有错别字,请多多包涵。

编辑:在我看来,很多人都忽略了问题的重点。我知道如何使用指针,甚至知道如何将指针包装在一个漂亮的模板中。问题被标记为“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); }
}

请注意没有默认构造函数,初始化构造函数采用引用,这使得此类不可为空。

唯一的问题是,访问最终的 T 成员是“.”运算符,不可覆盖,为此您需要其他东西。

简单的事情就是使用 * 和 -> as...

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

mutable_ref 声明中定义-

关于c++ - 一种在C++中交换两个引用的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15463321/

相关文章:

C 字符串转入数组

swift - Xcode Address Sanitizer 与 sockaddr 的问题

c++ - 按值或引用传递标量类型 : does it matter?

c# - 从方法 C# 返回数组

C++:引用包装器和 printf

c++ - 查询 std::ostringstream 内容

c++ - 我如何每秒仅处理 2 帧?如何退出 c 或 c++ 中的 while 循环?

c++ - Poco无法发送电子邮件

c++ - 休眠一个异步任务

c - 重新分配数组的行和列