面试中有人问我一个问题。
有没有一种方法可以将一个用户定义对象的值分配给另一个用户定义对象,而无需使用=运算符。
基本上,他要求我重载该类的赋值运算符,以使重载的赋值运算符转而不会使用原始类型=运算符。
memcpy
是正确的方法吗?
答案 0 :(得分:1)
问的问题: memcpy是正确的方法吗?并非总是如此。
暗示的问题:在不使用=的情况下重载赋值运算符?请使用Copy and Swap Idiom。
我将通过解释为什么提出的问题的答案为否来演示隐含的问题。
memcpy
执行二进制复制,而不对复制对象中的变量的性质应用任何上下文。这可能非常危险,并且只能用于trivially copyable的对象上。
请考虑以下情况:
struct A
{
int buffersize;
char * buffer;
A(int size):buffersize(size), buffer(new char[buffersize])
{
}
A(const A& source):buffersize(source.buffersize), buffer(new char[buffersize])
{
memcpy(buffer, source.buffer, buffersize);
}
~A()
{
delete[] buffer;
}
A& operator=(A source) // Assignment via Copy and Swap Idiom
{
std::swap(buffersize, source.buffersize);
std::swap(buffer, source.buffer);
}
}
这个例子非常愚蠢而且非常简单。任何理智的人都将使用std::vector
,但它确实实现了三规则(What is The Rule of Three?),因此可以安全地复制而不能被轻易复制。
看到副本构造函数中正在执行的工作吗? memcpy
将不会执行此操作。 memcpy
将复制地址buffer
的值,并留下两个指向同一buffer
的对象。如果不能立即证明共享缓冲区是致命的,那么最终两个析构函数都必须运行,并且buffer
将被释放两次。
注意memcpy
用于复制内部缓冲区。缓冲区是一个简单可复制的纯旧数据(POD)数组。如果它不是不可复制的,则应遵循πάνταῥεῖ的建议std::copy
。无论哪种情况,我们都应该使用std:::copy
,以便将来更容易修改代码,但是该示例并未显示安全使用memcpy
。