简体   繁体   English

带有std :: begin(),std :: end()问题的C ++ 11 auto迭代器类型

[英]C++11 auto iterator type with std::begin(), std::end() issue

I have some private class member, representing random access array of std::deque containing some data: 我有一些私有类成员,表示包含一些数据的std::deque随机访问数组:

std::vector<std::deque<SomeDataClass> > someMember;

I would like to provide a public class method which returns iterable data structure, containing all data elements from my array of deques: 我想提供一个公共类方法,它返回可迭代的数据结构,包含我的deques数组中的所有数据元素:

std::deque<SomeDataClass> someMethod();

I would like this method go through all the deques in vector and copy every element on it's way to local std::deque, eventually returning this local std::deque by value. 我希望这个方法遍历vector中的所有deques并复制它上面的每个元素到本地std :: deque,最终按值返回本地std :: deque。 I'm trying to implement this method using C++11 auto and std::begin() , std::end() : 我正在尝试使用C ++ 11 autostd::begin()std::end()实现此方法:

std::deque<SomeDataClass> MyClassName::someMethod(){
    std::deque<DirectedEdge> allDataItems;
    std::deque<DirectedEdge>::iterator deqIter = allDataItems.begin();
    for(auto it = std::begin(someMember); it != std::end(someMember); ++it){
        std::copy(std::begin(*it), std::end(*it), deqIter);
    }

    return allDataItems;
}

I receive data access violation unhandled exception error on runtime in deque header. 我在deque标头中的运行时收到数据访问冲突未处理的异常错误。 What is a mistake? 什么是错误?

std::copy() requires the destination range to be large enough to hold the copy, but allDataItems is empty. std::copy()要求目标范围足够大以容纳副本,但allDataItems为空。 You'd have to reserve space in allDataItems in advance (but that's not possible with std::deque ). 您必须提前在allDataItems中保留空间(但这对于std::deque不可能的)。 You should use a std::back_inserter (defined in <iterator> ) instead: 您应该使用std::back_inserter (在<iterator>定义):

std::deque<SomeDataClass> MyClassName::someMethod(){
    std::deque<DirectedEdge> allDataItems;
    for(auto it = std::begin(someMember); it < std::end(someMember); ++it){
        std::copy(std::begin(*it), std::end(*it), std::back_inserter(allDataItems));
    }

    return allDataItems;
}

Here is an idomatic C+11 way to do it: 这是一个习惯性的C + 11方法:

std::deque<SomeDataClass> MyClassName::someMethod() {
  std::deque<DirectedEdge> allDataItems;

  for( auto const& dq : someMember ) {
    allDataItems.insert( allDataItems.end(), std::begin(dq), std::end(dq) );
  }
  return allDataItems;
}

another way would be to write a concatinate function: 另一种方法是编写一个concatinate函数:

struct concatenate {
  template<typename Dest, typename Src>
  Dest&& operator()( Dest&& d, Src const& s ) const {
    using std::begin; using std::end;
    typename std::decay<Dest>::type retval = std::forward<Dest>(d);
    retval.insert( end(retval), begin(s), end(s) );
    return std::move(retval);
  }
};
std::deque<SomeDataClass> MyClassName::someMethod() {
  using std::begin; using std::end; // enable ADL
  return std::accumulate(
    begin(someMember), end(someMember),
    std::deque<DirectedEdge>(), concatenate()
  );
}

which is pretty cute. 这很可爱。 If you don't like std::accumulate , 如果你不喜欢std::accumulate

std::deque<SomeDataClass> MyClassName::someMethod() {
  std::deque<DirectedEdge> allDataItems;

  for( auto const& dq : someMember ) {
    allDataItems = concatenate( std::move(allDataItems), dq );
  }
  return allDataItems;
}

both of which are roughly equivalently efficient. 这两者大致相当有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM