以下面给出的类为例,它基本上只是一个类中的数组。
class MyArray{
public:
MyArray(int maxCapacity = 1024){
ptr = new int[maxCapacity];
numOfElements = 0;
}
~MyArray();
private:
int numOfElements; // current number of elements in array
int *ptr; //pointer to the array data
};
为这样的类实现复制构造函数的最佳方法是什么。
我和一位朋友正在就此发表争论。
我的信念是,它需要你有另一个容量变量来存储构造函数的maxCapacity参数,但是当在考试中给出这个问题时,这个变量就不包括了。
我的朋友认为,根据numOfElements变量的值(以任意方式)执行创建新数组的副本就足够了。
我对他的建议的问题是,这不是严格意义上的“深层复制”,因为我认为深层复制意味着除了内存位置之外,新对象在各个方面都是相同的。
谢谢, 丹
答案 0 :(得分:0)
为这样的类实现复制构造函数的最佳方法是什么。
嗯 - 算法非常简单。将A复制到B(这样做MyArray A; MyArray B(A)
)时,这里的方法是:
A.numOfElements
元素B.numOfElements
设为A.numOfElements
,numOfElements
元素从A.ptr
复制到B.ptr
(可能会调用memcpy
或 - 最好 - std::copy
)。考虑到你的第二个问题:
我的信念是,它需要你有另一个容量变量来存储构造函数的maxCapacity参数(...)我的朋友认为执行一个副本,根据numOfElements变量的值创建新数组(以任意方式)就足够了。
引用Wikipedia(我强调的文字):
对象副本是计算数据对象其属性复制到同一数据类型的另一个对象的操作。
所以答案是:是的,这就足够了,因为maxCapacity
不是MyArray
的属性。当您实际复制一个对象的内容到另一个对象时,会产生深度复制(不仅仅指向现有的对象,例如执行浅拷贝 )。在这种情况下,由于A
实际存储numOfElements
元素,我们可以假设 - 即使可以包含更多 - 其余的只是垃圾,所以我们不需要复制它。
另一方面 - 该课程可能设计不当。访问ptr
的元素时,无法检查我们是否正在访问我们可以访问的内存,或者尝试设置不属于我们的内存。因为类本身不存储有关数组大小的信息,所以它无法警告我们溢出(它可以“崩溃”,但这可能不是设计类的最佳方法)。虽然它是一种特殊的设计,但它不会干扰实际复制MyArray
的内容。
答案 1 :(得分:0)
你说:
我的信念是,它需要你有另一个容量变量来存储构造函数的maxCapacity参数,但是当在考试中给出这个问题时,这个变量就不包括了。
我们说你有:
MyStruct a(100);
MyStruct b(a);
构建a
后,a.ptr
的容量无迹可寻。您无法对用于访问a.ptr
中包含的数据的索引执行任何有效性检查。严格来说,您不需要 来存储使用a
的最大容量,但它肯定会有助于调试和错误检查。
但是,如果您没有在课程中存储最大容量,则必须假设b
的最大容量,这可能与a
的最大容量不同。
你说:
我的朋友认为,根据numOfElements变量的值(以任意方式)执行创建新数组的副本就足够了。
这是主观的。它取决于应用程序中对象的用法。如果你不希望b.ptr
的大小超过a.numOfElements
的大小,那么你的朋友有一个观点。您可以将其用作b
的最大容量。
你说:
我对他的建议的问题是,这不是一个严格的“深层复制”。因为我认为深层复制意味着除了内存位置之外,新对象在各方面都是相同的。
我认为,从严格的理论角度来看,你是对的。从可用性的角度来看,你朋友的建议可能就足够了。再一次,它取决于您的应用程序中这些对象的使用方式。
结论
我认为将maxCapacity
作为成员变量是一个更好的设计。额外的记忆并不重要。处理它的额外代码也不会太多。
如果您被允许使用std::vector
,您应该使用它而不必考虑太多。这比管理课堂内存更好。