刚开始使用C ++(现在几天),我来自C背景。
我有一个类,主要包含一个指向int数组的指针,代码如下:
class Array
{
private:
int * _arr;
int _size;
public:
Array();
Array(int size);
Array(const Array& obj); // copy constructor
~Array();
void readInValues();
void mult(int num);
void add(int num);
void printArray();
};
_arr是一个指向int数组的指针,当使用复制构造函数创建一个新实例时,我会在堆上创建一个新的int数组(我认为)。在复制构造函数中:
Array::Array( const Array & obj )
{
_arr = new int[_size];
for(int i=0;i<_size;i++)
*_arr[i] = *obj._arr[i];
}
我做的第一件事就是为新数组分配内存(_size是一种原始类型,因此据我所知自动复制)。我想做的下一件事是使用循环复制数组本身。这部分未通过编译说非法间接。我不知道为什么......
答案 0 :(得分:4)
此:
Array::Array( const Array & obj )
{
_arr = new int[_size];
for(int i=0;i<_size;i++)
*_arr[i] = *obj._arr[i];
}
可能是这样的:
Array::Array( const Array & obj )
: _arr(obj._size ? new int[obj._size] : nullptr)
, _size(obj._size)
{
if (_arr)
std::copy(obj._arr, obj._arr+_size, _arr);
}
具体来说,请注意初始化列表的使用。其他值得一提的事情:
不要使用带有前导下划线的标识符。除了使代码成为阅读之前的痛苦之外,您还可以快速找到自己使用实现保留的标识符。在这里情况并非如此,但我愿意打赌这不是故意的。
您还需要一个赋值运算符来完成Rule of Three。值得庆幸的是,一个像样的复制构造函数可以实现这一点。
不要任何。这就是为什么,在设计决策中大肆挥霍和咬牙切齿的时候,多年来的全能C ++标准委员会已选择用std::vector<>
祝福我们。如果你这样做是为了学习,那就好。你最终将学到的是,一旦你拥抱标准图书馆及其所有的内疚乐趣,你很少需要。
如果这是一个学习练习,请赞扬,并幸福地忽略上述(3)。对于(2),您可以使用copy/swap idiom现在您拥有合理的复制文件:
Array& Array::operator =(Array obj) // value-param intentional
{
std::swap(_arr, obj._arr);
std::swap(_size, obj._size);
return *this;
}
祝你好运。
答案 1 :(得分:0)
_size
没有初始值,因为您在使用它之前没有将其作为参数传递或在其他地方初始化。
另外,请勿*_arr[i] = *obj._arr[i];
它没有意义,因为arr[i]
本身意味着*(arr+i)
。
执行:
_arr[i] = obj._arr[i];
答案 2 :(得分:0)
当你这样做时,你应该没事
Array::Array( const Array & obj ):
_size(obj._size)
{
_arr = new int[_size];
for(int i=0;i<_size;i++)
_arr[i] = obj._arr[i];
}
在第2行,您会获得初始化列表,请阅读此http://www.cprogramming.com/tutorial/initialization-lists-c++.html
关键是,当您编写自定义复制构造函数时,只会复制您明确表示要复制的内容。复制构造函数将首先为所有成员调用默认的initilizer,除非您使用初始值设定值。
另外,对于性能的微小提示,你有没有看过memcpy? http://www.cplusplus.com/reference/cstring/memcpy/它可能更有效:D
我注意到的另一件事是你取消引用* _arr [i],它不是指针而是对值的引用。
编辑有人注意到我的更好甚至不是更好。我改变了它。答案 3 :(得分:0)
正在复制的原始类型_size实际上是一个真实的陈述,但你没有指定完整的句子。
当您没有声明复制构造函数时,默认实现将是这个
Array::Array( const Array & obj )
{
this._size = obj._size;
this._arr = obj._arr;
}
您不希望这样,因为复制的对象将共享_arr变量
但是,当您实现了复制构造函数时,您需要完全实现它。
在您的情况下,您没有使用_size
的值。因此它将是未定义的。
编译失败是由行*_arr[i] = *obj._arr[i];
引起的。您使用*使用非法间接。只需使用_arr[i] = obj._arr[i];
进行复制即可。
答案 4 :(得分:0)
这是我的解决方案。也许会有所帮助。
Array.h
#pragma once
class Array {
public:
Array();
Array(int size);
Array(const Array& src);
Array operator=(const Array& rhs);
~Array();
void readInValues();
void mult(int num);
void add(int num);
void printArray();
private:
int *_arr;
int _size;
};
我在参考三条规则时添加了赋值运算符。它是Array.cpp
#include "Array.h"
Array::Array()
:_size(10) {
_arr = new int[_size];
}
Array::Array(int size)
: _size(size) {
_arr = new int[_size];
}
Array::Array(const Array& src) {
_size = src._size;
_arr = new int[_size];
for (int i = 0; i < _size; i++) {
_arr[i] = src._arr[i];
}
}
Array Array::operator=(const Array& rhs) {
if (this == &rhs) {
return (*this);
}
delete[] _arr;
_size = rhs._size;
_arr = new int[_size];
for (int i = 0; i < _size; i++) {
_arr[i] = rhs._arr[i];
}
}
Array::~Array() {
delete[] _arr;
}