所以,我觉得这是一个坏主意:
class Foo
{
public:
Foo(const Foo& from)
{
memcpy(this, &from, sizeof(Foo));
m_someData = new int[m_dataLength];
memcpy(m_someData, from.m_someData, m_dataLength * sizeof(int));
}
private:
int* m_someData;
int m_dataLength;
};
问题是:为什么?如果memcpy
参数的类型(和大小)相同,布局相同,哪里不好?
我看到的一个潜在问题是,如果有string
或vector<>
字段,但我不确定这是否是一个有效的问题。
答案 0 :(得分:7)
如果可以推导出Foo
,请考虑当您从Bar
派生Foo
类时会发生什么,并从{{1}复制构造Foo
实例。
如果你有任何虚拟方法,你的Bar
包括编译器为实现虚拟方法(意味着vtable)而添加的任何信息,你肯定不想复制它们。
如果您没有任何虚拟方法,但sizeof(Foo)
向Bar
添加了一个字段,那么您仍有潜在的问题:该字段可以存储在{{1的填充字节中}}。他们会受到Foo
的打击。
最后:
我看到的一个潜在问题是,如果有
Foo
或memcpy
字段,但我不确定这是否是一个有效的问题。
为什么不呢?它会明显破裂,而且会破坏。
您可以使用默认自动生成的复制构造函数来避免此问题。如果要为其添加逻辑,而不是强制提及要复制的所有字段,请使用隐藏数据容器:
string
请注意vector<>
这里的class Foo
{
public:
Foo(const Foo& from)
{
m_Data = from.m_Data;
m_Data.m_someData = new int[m_Data.m_dataLength];
memcpy(m_Data.m_someData, from.m_Data.m_someData, m_Data.m_dataLength * sizeof(int));
}
private:
struct Data {
int* m_someData;
int m_dataLength;
// more fields
};
Data m_Data;
};
如何与m_Data = from.m_Data;
达到的确切效果相同,但安全性除外。
答案 1 :(得分:2)
为什么这是错的:
struct boom1 {
boom1(const boom1& from)
// reason 1: not using an initialisation list means double-initialisation of members. inefficient.
{
// reason 2: undefined behaviour on all subsequent access to
// this->_s or from._s after this line
memcpy(this, &from, sizeof(from));
// reason 3: what if someone derived from this class? didn't you just overwrite the RTTI info pointer??
}
// reason 4: c++ already generates a copy constructor that does the right thing automatically. why are you laying mines for other developers?
std::string _s;
}
“是的,但我的特殊课程是POD而且我能控制它”......
...直到其他人从中获取,修改它或尝试维护它。
不,不,不。这是永远不对的。总是错的。确保你的学生理解这一点。有一天,他可能正在编写谷歌汽车。你现在不想让它过你的孩子吗?