c++ - 在低级别实现交换复制位会出现什么问题?

标签 c++ swap

考虑这段代码:

#include <cstring>
#include <memory>

namespace mstd {
template <typename T>
void swap(T& lhs, T& rhs) {
    char tmp[sizeof(T)];

    std::memcpy(tmp, std::addressof(lhs), sizeof(T));
    std::memcpy(std::addressof(lhs), std::addressof(rhs), sizeof(T));
    std::memcpy(std::addressof(rhs), tmp, sizeof(T));
}
}

使用mstd::swap一般来说不安全;仅当 std::is_trivially_copyable<T>::value是真的。

但是我看不出它怎么会出错。有谁知道使用此交换会带来不正确交换行为的真实示例,为什么?

最佳答案

假设一个类包含一个指针,该指针必须指向它自己的成员之一。它将需要复制/移动语义来保留该不变性。字节复制将忽略这些语义,使其错误地指向不同对象的成员。

举一个具体的例子,考虑一个具有“小字符串优化”的字符串。如果字符串足够小,它包含一个嵌入式缓冲区来代替动态内存;和一个指向该缓冲区或动态内存的指针。它需要重要的复制(和移动)操作来确保指针不被复制,而是指向目标对象的缓冲区:

string(string const & other) :
    size(other.size),
    data(other.data == other.buffer ? buffer : new char[size])
{
    copy(other.data, other.data+size, data);
}

(两个小字符串的)字节交换将使每个字符串指向另一个字符串的缓冲区。如果一个指针在另一个指针之前被销毁,你最终会得到一个悬空指针;更糟糕的是,析构函数实现为

~string() {if (data != buffer) delete [] buffer;}

会删除不应该删除的内容,从而产生未定义的行为。

关于c++ - 在低级别实现交换复制位会出现什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29912437/

相关文章:

r - 如何交换(翻译)向量内的值

python - 交换列表中的最大值和最小值

c++ - C++-没有自定义交换功能的移动赋值运算符?

c++ - 读取和写入 USACO 文件

c++ - 针对特定机器/处理器架构进行优化

c++ - 使用 MinGW 进行 C++ 的 DLL 管理?

python - 在python中mlock一个变量

java - 组织 K 内所有元素所需的最小交换

c++ - 为什么在 C 中直接将无符号转换为有符号会给出正确的结果?

C++ 外观避免复制