在低级别实现交换复制位时可能会出现什么问题
What can go wrong implementing swap copying the bits at low level?
请考虑以下代码:
#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;}
将删除不应该删除的内容,从而给出未定义的行为。
我想
我理解正确,所以我会把这个作为一个答案。
如果类的 ctor 和相应的复制 ctor 具有某些副作用,则按位复制不会考虑这些副作用。例如:如果一个对象在创建时通过地址在中央注册表中注册自己,例如因为它是一个回调函子。然后,交换后地址将指向错误的对象。在示例中,错误的回调将由回调持有者执行。
我想到的一个例子是一个类,其中孩子有一个指向自己父级的指针:
#include <memory>
struct Parent;
struct Child{
Parent* parent;
};
struct Parent {
std::unique_ptr<Child> child;
};
void swap(Parent& lhs, Parent& rhs) {
std::unique_ptr<Child> tmp(std::move(lhs.child));
lhs.child=std::move(rhs.child);
rhs.child=std::move(tmp);
//there is no equivalence for those two lines in your example
lhs.child->parent=&lhs;
rhs.child->parent=&rhs;
}
例如,你在Qt中经常遇到这种情况。
相关文章:
- 警告处理为错误这里有什么问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 当我尝试添加 2 个大字符串时,我无法弄清楚出了什么问题
- 违反const正确性:我应该现实地期待什么问题
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- 我的逻辑反转字符串中的元音有什么问题?
- 需要以下代码的帮助,下面的代码有什么问题
- 常量公共成员有什么问题?
- c++无值sort()的问题是什么?
- 以下代码中的函数模板有什么问题?
- 这个返回元素位置的基于循环的函数有什么问题?
- creat_list2功能有什么问题?
- 基本的 c++ 问题:如果我在函数中创建某些内容并返回它会发生什么?
- 我遇到了黑客排名中的问题"TWO STRINGS"的三个测试用例的分段错误。原因是什么?
- 什么是钻石问题?是一系列问题还是特定问题?
- 格式说明符C++有什么问题
- 我应该在 main 函数中写什么来测试我的问题?
- 任何人都可以告诉我我的 C++ 代码出了什么问题?
- 方法问题 - 什么会改变值,什么不会改变?什么是无效的?