我最近编写了一个非常简单的class
代码,它负责查找std::vector
中的最小值和最大值并发现,即使我将集合作为{{1}传递} const reference
'构造函数,然后从外部更改向量(即将元素推入其中或从中移除一个元素),class
内的向量保持不变。
class
我认为传递引用的点是为了不复制大对象,但是我的代码现在的工作方式似乎是复制集合。
#include <vector>
#include <algorithm>
class MinMaxFinder
{
public:
MinMaxFinder(const std::vector<int>& numbers) : numbers(numbers)
{
}
const int Min() const
{
this->findMinAndMax();
return this->min;
}
const int Max() const
{
this->findMinAndMax();
return this->max;
}
protected:
std::vector<int> numbers;
int min;
int max;
void findMinAndMax()
{
// std::minmax_element call to find min and max values
}
};
#include <vector>
#include <iostream>
#include "MinMaxFinder.h"
int main(int argc, char* argv[])
{
std::vector<int> v{ 1, -6, 12, 158, -326 };
MinMaxFinder mmf(v);
v.push_back(-9999999);
v.push_back(9999999);
auto min = mmf.Min();
auto max = mmf.Max();
}
的值为min
,-326
的值为max
,即使值158
非常清楚比9999999
大得多。
我设法通过将私有成员158
的定义更改为numbers
来解决此问题,但这是正确的解决方案吗?
但是,为什么内部集合的状态仍然没有变化,它是否不会违反常量传递的定义?
答案 0 :(得分:6)
ApplicationContext
应为std::vector<int> numbers;
,这样您就可以在不复制对象的情况下引用对象,也可以更改对象。
但严肃的说,这堂课有什么意义?巨大的矫枉过正!只需使用const std::vector<int>& numbers;
和std::min_element
或std::max_element
..
std::minmax_element
答案 1 :(得分:3)
我认为传递引用的点是为了不复制大对象
是的,没错,当&#34;调用&#34;时,不会复制大对象。构造函数。
但是,您的数据成员是值,而不是引用,因此会立即复制参数以初始化成员。
这就像写这个:
std::vector<int> v;
const std::vector<int>& ref = v;
std::vector<int> v2 = ref;
然后想知道为什么v2
是副本。 :)
答案 2 :(得分:2)
在构建上调用的成员初始化numbers(numbers)
将进行深层复制。
如果您要计算构造的最小值和最大值,那么您不需要将numbers
保留为类成员。
您可以存储引用作为类成员,但是您必须小心将类实例的生命周期限制为向量在范围内,否则引用可以悬挂。我建议不要这样做。
答案 3 :(得分:0)
成员varialbe numbers
未声明为引用,因此在初始化时将复制它,即使ctor的参数是通过引用传递的。尝试将声明更改为:
protected:
const std::vector<int>& numbers;