6

使用这种交换实现的最大威胁是什么?除了线程安全和糟糕的优化。什么时候失败(反例)?

template<typename T>
void swapViaMemory(T& left, T& right) {
    if(&left == &right) { return ; }

    unsigned int tSize = sizeof(T);
    unsigned char* lPtr = reinterpret_cast<unsigned char*>(&left);
    unsigned char* rPtr = reinterpret_cast<unsigned char*>(&right);

    for(unsigned int i = 0; i < tSize; ++i) {
        *(lPtr + i) ^= *(rPtr + i);
        *(rPtr + i) ^= *(lPtr + i);
        *(lPtr + i) ^= *(rPtr + i);
    }
}

抱歉语法错误和拼写错误(=

4

5 回答 5

5

如果 T 不是可简单复制的类型,它会调用未定义的行为。

于 2012-12-05T00:37:40.883 回答
4

它无法传达意图。

这是代码的主要目的。

template<typename T>
   typename std::enable_if<std::is_pod<T>, void>::type 
   swapViaMemory(T& left, T& right) 
{
    using std::swap;

    swap(left, right);
}
于 2012-12-05T00:35:04.300 回答
4

如果T包含一个成员,该成员是指向其另一个成员的指针或引用,这将失败(假设意图是指针/引用成员始终指向/引用属于该实例的数据成员)。

struct foo
{
  foo() : i(), ref_i(i), ptr_i(&i) {}
  int i;
  int& ref_i;
  int *ptr_i;
};

如果两个foo对象,比如说f1&f2在交换后使用swapViaMemory, 交换,f1.ref_i并且f1.ptr_i将引用 / 指向,f2.i反之亦然。此外,在引用成员的情况下,这会调用未定义的行为,因为重新定位引用是非法的。

于 2012-12-05T00:40:37.213 回答
1

说:

struct B{ 
   virtual ~B() {}
};
struct X : B
{
   int x;
   ~X() { std::cout << x; }
};
struct Y : B
{

};

//...
X x = X(); 
Y y;
swapViaMemory<B>(x,y);
于 2012-12-05T00:39:08.927 回答
0

如果 left 和 right 的演员表指向同一个地址,除了被严重混淆之外,它还会失败。

由于a^a = 0(这是您用于此“技巧”的内容)

如果left == right(并假设它是一个 1 字节的实体,包含'a' Then 您将执行以下操作:

a^a = 0
0^a = a
a^a = 0
于 2012-12-05T00:35:44.987 回答