【发布时间】:2018-11-14 19:12:21
【问题描述】:
这是一个简单的程序,它应该处理一个动态的数字数组,然后过滤掉偶数元素并将它们放入一个新数组中,然后在屏幕上打印这两个数组。
这是头文件:
#pragma once
namespace filter
{
class Array
{
double *arr;
int n;
public:
Array();
Array(int);
Array(const Array&);
Array(Array&&);
void PutIn();
void PrintOut() const;
Array isEven();
Array filter(const std::function<bool(int)>&) const;
~Array();
};
}
那么,这是函数的实现:
#include <iostream>
#include <functional>
#include "Array.h";
using namespace filter;
using namespace std;
Array::Array() :arr(nullptr), n(0)
{ }
Array::Array(int n)
{
this->n = n;
arr = new double[n];
}
Array::Array(const Array &a1)
{
n = a1.n;
arr = new double[n];
for (int i = 0; i < n; i++)
arr[i] = a1.arr[i];
}
Array::Array(Array &&a1)
{
n = a1.n;
for (int i = 0; i < n; i++)
arr[i] = a1.arr[i];
a1.n = 0;
a1.arr = nullptr;
}
void Array::PutIn()
{
cout << "Insert elements:\n";
for (int i = 0; i < n; i++)
cin >> arr[i];
}
void Array::PrintOut() const
{
cout << "\nYour array is :\n";
for (int i = 0; i < n; i++)
cout << arr[i] << "\t";
}
Array Array::isEven()
{
return filter([](int x) { return x % 2; });
}
Array Array::filter(const std::function<bool(int)> &f) const
{
int b = 0;
for (int i = 0; i < n; i++)
if (f(arr[i]) == 0)
b++;
Array temp(b);
b = 0;
for (int i = 0; i < n; i++)
if (f(arr[i]) == 0)
{
temp.arr[b] = arr[i];
b++;
}
return temp;
}
Array::~Array()
{
delete[]arr;
n = 0;
}
最后,这是源代码:
#include <iostream>
#include <functional>
#include "Array.h"
using namespace filter;
using namespace std;
int main()
{
Array a(5);
a.PutIn();
Array b = a.isEven(); //WHY THIS LINE OF CODE INVOKES MOVE CONSTRUCTOR AND NOT COPY CONSTRUCTOR?
a.PrintOut();
b.PrintOut();
getchar();
getchar();
}
所以,如您所见,这是一个相对简单的程序,它需要处理用户输入的包含五个元素的数组,然后创建一个由第一个数组的偶数元素组成的新数组。当我运行它时,它工作正常,但是,这里有一点我不明白。
如果您查看源代码,请注意我留下评论的那一行,即调用 move 构造函数的那一行,但我不知道为什么。这意味着 a.IsEven() 是一个 RVALUE,因为移动构造函数与 RVALUES 一起使用,对吗?谁能解释我为什么这是右值以及理解它的正确方法是什么?任何帮助表示赞赏!
【问题讨论】:
-
isEven按值返回Array,这是一个临时的,因此它肯定会调用b的移动构造而不是副本。 -
让移动构造函数分配一个新数组有什么意义?关键是,鉴于源对象可以“空”,您可以窃取他的指针...目前您的实现复制然后泄漏源对象内存。
-
根据rule of 3/5/0,您将需要一个赋值运算符。请注意,您的移动构造函数不仅不会移动,还会泄漏。
-
我不认为这段代码“相对简单”。其实我觉得这个比较复杂。手动内存管理绝非易事。只是说...
-
除非这是“不要以 c++ 方式执行”任务之一,否则您应该使用
std::array