不明白 std::iterator 在列表初始化中是如何工作的 [duplicate]

Don't understand how std::iterator works in list initialization [duplicate]

提问人:oronr 提问时间:11/16/2023 更新时间:11/16/2023 访问量:46

问:

我在使用 . 时遇到问题。首先,我定义了一个:std::vector::iteratorstruct

template <typename T>
struct VecIter {
  VecIter(std::vector<T>::iterator &&it_, size_t remain_):
    it(it_), remain(remain_) {}

  std::vector<T>::iterator &it;
  size_t remain;

  T& operator * () {
    return *it;
  }
};

它只是一个常规迭代器的包装器。下面是一个测试类:

template <typename T>
class testA {
  public:
    testA(std::vector<T> &a) {
      stack.push_back({a.begin(), a.size()});
    }

    std::vector<VecIter<T>> stack;
};

构造函数将 a 作为输入并初始化我们的迭代器包装器。测试部分如下:std::vector

TEST(TestIterator, test_iter_in_stack) {
  std::vector<int> a{3, 2, 1};

  testA<int> sol(a);
  auto x = sol.stack[0];
 
  auto it = x.it;  // extract the iterator
  cout << *it << "\n";  // segmentation fault here...
  it++;
  cout << *it << "\n";
}

我的问题是为什么这里会导致分段错误?我怀疑列表初始化没有成功传递迭代器。*itstack.push_back({a.begin(), a.size()})

我希望测试应该打印出来并且.欢迎任何评论。谢谢!32

C++ 迭代器

评论

1赞 Öö Tiib 11/16/2023
似乎您已经制作了引用包装器,请参考临时迭代器对象 a.begin() 对其进行初始化,该对象在push_back后留下范围。然后你有纠缠不清的参考和未定义的行为,允许恶魔从你的鼻子里出来。
0赞 user12002570 11/16/2023
什么是悬空引用?
0赞 Pete Becker 11/16/2023
请注意,尽管有标题,但问题是关于 ,而不是 .后者是许多人认为毫无意义的帮手。std::vector::iteratorstd::iterator

答:

1赞 Alan Birtles 11/16/2023 #1

VecIter::it是对 返回的临时对象的悬空引用。应更改为 .a.begin()std::vector<T>::iterator &itstd::vector<T>::iterator it

一般来说,迭代器可能只不过是一个指针,通过引用传递和存储它们不太可能是必要的。标准库通常按值传递它们,例如在 std::vector 构造函数中。