BigInt C++和正确的复制构造函数
BigInt C++ and proper copy constructor?
我正在尝试为C++实现BigInt,但遇到了复制构造函数的问题。你可以看到,我注释掉了复制构造函数的原始代码,它只是*this = orig;
。但我发现您需要使用指针来执行此操作。然而,我不完全确定这是如何工作的,目前代码没有正确地生成复制构造函数。
-BigIntVector是一个自定义向量类。与STL矢量进行比较。
BigInt.h:
class BigInt {
private:
BigIntVector bigIntVector;
bool isPositive;
int base;
unsigned int skip;
BigIntVector* ptr; //pointer to copy?
public:
// copy constructor
BigInt(BigInt const& orig);
// constructor where data value is passed as a long
BigInt(long num);
// destructor
~BigInt();
// binary '+' operator
BigInt operator+(BigInt const& other) const;
// unary '+' operator
BigInt operator+() const;
//more operator unloading functions
以下是我目前在BigInt.cpp中实现的构造函数:
// copy constructor
BigInt::BigInt(BigInt const& orig) {
ptr = new BigIntVector;
*ptr = *orig.ptr;
//*this = orig;
}
// constructor where operand is a long
BigInt::BigInt(long num) {
//this->data = num;
ptr = new BigIntVector;
base = 10;
int sizeOfLong = 0; //holds size of num
int tempNum = num;
//get size of num
if (tempNum == 0) {
sizeOfLong = 1;
}
while (tempNum != 0)
{
tempNum /= 10;
++sizeOfLong;
}
//resize vector to match size of long
bigIntVector = BigIntVector(sizeOfLong);
if (num < 0) {
isPositive = false;
num *= -1;
}
else {
isPositive = true;
}
long pushedNum;
//cout << "num: " << num << endl;
for (int i = sizeOfLong - 1; i >= 0; --i) {
pushedNum = (long)(num%base);
bigIntVector.setElementAt(i, pushedNum);
num /= base;
}
}
// destructor
BigInt::~BigInt() {
//delete *this;
}
//code for overloading operators for BigInt below
BigIntVector构造函数的代码:
BigIntVector::BigIntVector(long initialSize)
{
vectorTotalSize = initialSize;
vectorIncrementSize = initialSize;
vectorArray = (long *)malloc(initialSize*sizeof(long));
for (long i = 0; i < initialSize; i++) vectorArray[i] = 0;
nextValue = 0;
}
在现实世界中(家庭作业之外),BigInt
类不应该需要显式的复制构造函数。内存分配应该委托给一个单独的类——很可能是std::vector
。如果您需要一个指针作为类成员(在这种情况下不太可能),那么使用std::shared_ptr
管理它就不需要复制构造函数了。
这是我之前的一篇文章,解决了您对C++中使用new
的误解。该描述中对C#的引用同样适用于Java:在标准C++中垃圾收集是自动的吗?
关于评论中的一个问题:"正式成员的语法是什么"。暗示这一点的评论只是说不要将元素声明为指针(只需省略*
)。总之,对于此类:
- 你不需要指针
- 你不需要复制构造函数
- 您不需要使用
new
关键字
在这种情况下,问题出在BigIntVector
类中。由于这是一个分配内存和管理指针的程序,因此它需要一个复制构造函数。如果这是一项家庭作业,我建议将三条规则应用于BigIntVector
的实施。您将需要以下所有:
- 复制构造函数,用于复制内存
- 赋值运算符,它还复制内存
- 析构函数,用于释放内存
如果不是家庭作业,我建议用std::vector
代替BigIntVector
。
为非平凡类声明复制构造函数是个坏主意,因为您通常需要显式复制每个成员(或者它们将被默认初始化而不是复制)——最好让编译器为您做这件事,以避免错误。
如果你必须有一个这样的任务,正确的形式应该是这样的:
BigInt::BigInt(BigInt const& orig)
: bigIntVector(orig.bigIntVector)
, isPositive(orig.isPositive)
, base(orig.base)
, skip(orig.skip)
{
// empty body
}
将算术运算符转发到复合分配运算符的规范形式是的一些变体
T& T::operator += ( T const & b )
{
...class-specific math logic that modifies the object...
return (*this);
}
T operator + ( T const & a, T const & b )
{
T temp(a); // create a temporary copy of 'a' rather than modifying it
return temp += b;
}
好吧。我不知道BigIntVector* ptr; //pointer to copy?
是干什么的,所以我认为这是个错误。你的代码应该是这样的:
class BigInt
{
private:
BigIntVector bigIntVector;
bool isPositive;
int base;
unsigned int skip;
public:
// constructor where data value is passed as a long
BigInt(long num = 0);
BigInt &operator+=(BigInt const& other);
// Other accessors...
};
inline BigInt operator+(BigInt a, BigInt const &b) { a += b; return a; }
这里的主要原则是零法则。你设计你的类,使默认生成的函数做正确的事情:复制构造函数,移动构造函数,移动赋值,复制赋值,析构函数。
那么类的定义仍然很简单。为了实现这一目标,所有数据成员都必须正确地实现这些函数——要么遵循零规则,要么实际拥有这些函数。
内置类型都遵循规则,我假设BigIntVector
遵循0.3或5的规则。(如果没有,修复它,这样它就可以了!)
我做的其他更改是:
- 将非可变运算符作为非成员函数是一种很好的风格。如果您发现自己能够将
const
放在成员运算符上,那么它应该是非成员是一个好兆头。有关此主题的更多信息,请参阅本线程 - 注释应该说明代码所说的内容之外的其他内容。在析构函数上加上注释"析构函数",或在二进制+运算符上加上"二进制+运算符",都会毫无理由地扰乱屏幕
在long
构造函数中,int tempNum = num;
应该是long tempNum = num;
;并且应该初始化skip
。
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 当从函数参数中的临时值调用复制构造函数时
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 复制构造函数、赋值运算符C++
- std::ofstream 作为类成员删除复制构造函数?
- 复制构造函数C++无法正确复制指针
- 关于复制构造函数的一个棘手问题
- 为什么调用复制构造函数而不是移动构造函数?
- 填充上编译器生成的复制构造函数之间的不一致
- C++ 对象指针数组的复制构造函数
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 防止在复制构造函数中隐式调用基构造函数
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 具有已删除移动和复制构造函数的类的就地构造
- 复制构造函数隐式转换问题
- 复制构造函数中的递归调用