C ++ 11 - 从函数传递向量作为迭代器

时间:2013-08-10 22:28:28

标签: c++11 vector stl

这可能是一个简单的问题,然而,这引起了很多困惑。

我有一个类成员,它返回一个填充的向量:

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

2 个答案:

答案 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();

通常,最好避免将原始指针返回到已分配的数据。