这是很好的代码?(复制构造和分配运营商)
-
12-09-2019 - |
题
由于种种原因,我被迫提供复制构造和运营商=为我的课。我想我不需要 operator=
如果我定义的一个副本构造函数,但是 QList
想要一个。把它放到一边,我讨厌代码重复,这样有错吗这样做?
Fixture::Fixture(const Fixture& f) {
*this = f;
}
Fixture& Fixture::operator=(const Fixture& f) {
m_shape = f.m_shape;
m_friction = f.m_friction;
m_restitution = f.m_restitution;
m_density = f.m_density;
m_isSensor = f.m_isSensor;
return *this;
}
只是出于好奇,有没有办法打开它这样大量的代码,在复制和构造函数 operator=
以某种方式利用它吗?我试过了 return Fixture(f);
但是它不喜欢那样
看来我需要使它更清楚,复制构造和分配运营商已经默示禁止通过类我是继承。为什么?因为这是一个抽象的基类不应该是实例在它自己的。这一类,但是, 是 意味着独立。
解决方案
这是不好的,因为operator=
不能依靠一个建立对象了。你应该这样做的其他方式,并可以使用复制交换成语。
在这里你就必须在所有元素复制的情况下,可以使用隐式生成的赋值运算符。
在其他情况下,你将不得不做一些此外,多释放和复制内存。这就是副本交换成语是良好的。它不仅是优雅的,但它也提供了这样的分配不会抛出异常,如果它只是交换原语。让我们一类指向你需要复制一个缓冲区:
Fixture::Fixture():m_data(), m_size() { }
Fixture::Fixture(const Fixture& f) {
m_data = new item[f.size()];
m_size = f.size();
std::copy(f.data(), f.data() + f.size(), m_data);
}
Fixture::~Fixture() { delete[] m_data; }
// note: the parameter is already the copy we would
// need to create anyway.
Fixture& Fixture::operator=(Fixture f) {
this->swap(f);
return *this;
}
// efficient swap - exchanging pointers.
void Fixture::swap(Fixture &f) {
using std::swap;
swap(m_data, f.m_data);
swap(m_size, f.m_size);
}
// keep this in Fixture's namespace. Code doing swap(a, b)
// on two Fixtures will end up calling it.
void swap(Fixture &a, Fixture &b) {
a.swap(b);
}
这就是我平时写的赋值运算符。阅读要速度?通过绕不寻常的赋值运算符签名值传递(按值传递)。
其他提示
复制构造函数和分配是完全不同 - 分配通常需要释放资源,它的替换对象,副本构造函数正在一个尚未初始化的对象上。因为在这里,你显然没有特殊要求(没有“释放”需要在分配),你的做法是好的。更一般地,你可能有辅助方法(在析构函数,并在指定的开始称作)“的对象是持有释放所有资源”还有“这些东西复制到对象”的一部分,这相当接近典型的拷贝构造函数的工作(或大部分,反正; - )。
你简单地做在你的例子成员明智的副本和任务。这是不是你需要自己写一些东西。编译器可以生成隐复制和赋值操作是这样做。你只需要当编译器生成的那些不适合写自己的拷贝构造函数,赋值和/或析构函数(即如果你通过指针或类似的东西管理一些资源)
我想你遇到的问题,如果您的运营商=真的成为虚拟的。
我会建议写,做,然后拷贝有拷贝构造和操作的功能(也许静态)=调用该函数。
是的,这是良好做法和应(几乎)总是能做到的。此外抛在一析构和默认的构造(甚至如果你把它私人).
在詹姆斯Coplien1991年书 先进C++, 这是描述为的一部分"正统的规范的形式"。在书中,他提倡一种默认的构造、复制构造、转让操作员和一析构函数。
在一般情况下,您 必须 使用正统的规范形式,如果:
- 你想要支持,分配的对象的类,或者希望通过这些对象,如按价值的参数的一个函数, 和
- 对象包含针对对象的基准计算,或类析构执行
delete
在一个数据对象的成员。你的 应该 使用正统的规范形式针对任何平凡的课程序,为统一跨类和管理日益复杂的各类过程的程序的演进。
Coplien提供的网页的原因,这种模式和我做不到他们的正义在这里。然而,一个关键项目已经涉及的是能够清除的对象是被复盖。
我想你应该使用initializer list
初始化对象的成员变量。如果您的变量是primitive-types
的,那么也没关系。否则,分配是从初始化不同。
您可以通过初始化copy constructor
到0
内的指针与一个小窍门做,那么你可以调用在assignment operator
安全地删除:
Fixture::Fixture(const Fixture& f) : myptr(0) {
*this = f;
}
Fixture& Fixture::operator=(const Fixture& f) {
// if you have a dynamic array for example, delete other wise.
delete[] myptr;
myptr = new int[10];
// initialize your array from the other object here.
......
return *this;
}