这可能是一个简单的问题,然而,这引起了很多困惑。
我有一个类成员,它返回一个填充的向量:
vector<double> returnVector()
{
return theVector;
}
我还有一个名为toArray()
的函数,它接受一个迭代器,这样我就可以在我传入的值的类型之间交替。例如:
template<typename T, typename Inverse>
T* toArray(Inverse begin, Inverse end)
{
size_t size = distance(begin, end);
auto pos = 0;
T* tmp = new T[size];
for(auto i = begin; i != end; i++)
{
tmp[pos] = *i;
pos++;
}
return tmp;
}
在我的主要内部,我认为可以做到以下几点;
MyClass class;
auto* var = Functs::toArray<double>(
std::begin(class.returnVector()),
std::end(class.returnVector())
);
然而,这不起作用,我似乎得到一些malloc错误。但是,我能够做到以下几点:
MyClass class;
vector<double> vals = class.returnVector();
auto* var = Functs::toArray<double>(
std::begin(vals),
std::end(vals)
);
有人可以解释为什么会这样吗?我假设因为函数returnVector
返回实际向量,因此可以从begin
访问end
?
答案 0 :(得分:3)
下面:
Functs::toArray<double>(
std::begin(class.returnVector()),
std::end(class.returnVector())
);
您的returnVector
方法按值返回,因此您可以获得副本。这意味着两个调用产生两个不同的向量。这就是为什么你得到比你想象的更大的范围,以及为什么你最终访问无效的内存。
如果您能够,请更改returnVector
以返回引用。但如果这不是一个选项,你只需记住总是存储一个本地引用,就像你在其他例子中那样。
另一个选择是定义一个方便的过载:
template<typename T>
T* toArray(std::vector<T>& vec) {
return toArray( std::begin( vec ), std::end( vec ) );
}
你可以像这样打电话:
auto* var = Functs::toArray( class.returnVector() );
就个人而言,我会选择这个选项。
答案 1 :(得分:2)
您的代码
size_t size = distance(begin, end);
如果end
(始终)无法从begin
[iterator.requirements.general] 访问,则具有未定义的行为。
这是使用toArray
的第一个示例的情况。第二个例子是有效的。
最好将returnVector
更改为
vector<double> const& returnVector() const;
而不是toArray
使用
vector<double>::data();
通常,最好避免将原始指针返回到已分配的数据。