2013-03-17 75 views
4

这实际上是关于交换两个引用的一个坏主意。这些参考资料不应该是可重置的,所以它不应该是可能的。我知道的很多。一种在C++中交换两个引用的方法

我想要做什么,是交换两个引用,在某种程度上人们会交换两个指针:地址被交换不是数据。假设:

int a = 0, b = 1; 
int *pA = &a, *pB = &b; 
std::swap(pA, pB); 

现在* Pa为1和* PB为0,但仍然是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); 

现在仍然是0和B仍然是1,内部RRA和无线电规则委员会中的引用交换。可惜,如果没有丑陋的操作符=(),它就无法工作。至少它在MSVC中适用于我,不知道g ++是否会接受它(但我想它应该)。

整个引用交换应该用在一个对象中,该对象使用内部引用另一个对象的方式构建,并且我想为它们创建一个swap()函数。我想避免使用指针,因为引用的非空值特性非常好。这也将是一个更好的设计(resetable_ref本身除外)。

有没有人有更好的想法如何去呢?任何人都可以想到一些兼容性/未定义的行为问题?

我编写了大部分代码而没有编译,如果您发现某些错误,请耐心等待。

编辑:在我看来,很多人都忽略了这个问题的重点。我知道如何使用指针,甚至是如何在漂亮的模板中包装指针。这个问题被标记为“hack”,这是预期的。不要告诉我像“不这样做,使用指针”的东西,因为这不是我问的。如果你不喜欢这个话题,不要回答,但不要因为你会使用指针而降低问题的质量。

+1

我想'的std :: reference_wrapper'可以工作。虽然从未真正使用它。 – chris 2013-03-17 16:44:00

+4

为什么不在你的类中使用一个指针而不是一个引用,使它成为私有的,然后提供合适的成员函数来充当底层'int'的访问器?这样,您可以避免所有令人讨厌的reinterpret_cast /潜在未定义行为问题。 – 2013-03-17 16:45:39

+0

@chris谢谢,我不知道存在 – 2013-03-17 16:48:19

回答

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); } 
} 

注意缺少缺省构造函数中,有一个初始化构造函数取一个参考,这使得该类不是空的。

唯一的问题是,要访问最终的T成员,是“。”操作员,不可覆盖,您需要为此目的选择一些东西。

简单的就是使用*和 - >为...

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

里面mutable_ref定义申述

+0

噢,我知道C++,我知道这可以做到。问题是如何交换引用。感谢您的回复,这是很好的代码。 – 2013-03-17 20:23:31

+0

问题是......它无法完成。这就是为什么我发布了一个“不完美的解决方法”,它只是定义了一个“mutable_reference”,不存在于C++核心语言中。 – 2013-03-18 08:27:16

+1

但我认为它是存在的:stdlib是“核心语言”的一部分,而stdlib包含'std :: reference_wrapper'。正如你所暗示的那样,由于缺少'operator.',现在用户必须编写'refwrap.get()。member' - 但是希望Bjarne和co下一次将'operator.'带入语言中; ) – 2016-09-18 16:33:09

相关问题