3参数形式list::splice()将单个元素从一个列表移动到另一个列表. SGI的文档明确声明所有迭代器,包括指向要移动的元素的迭代器仍然有效. Roguewave的文档没有说明splice()方法的迭代器失效属性,而C++标准明确声明它使所有迭代器和对被拼接元素的引用无效.
splicing()在实践中按照SGI的定义工作,但是我在微软的STL实现的调试/安全SCL版本中得到断言失败(解除引用无效迭代器)(严格遵循标准的字母).
现在,我正在使用list完全是因为我想在列表之间移动一个元素,同时保留指向它的迭代器的有效性.该标准对最初的SGI规范进行了极为无益的改变.
我该如何解决这个问题?或者我应该是务实,在沙把头(因为拼接并没有在实践中迭代器失效-甚至在MS的执行,一旦调试迭代器关闭).
我想提供两种迭代器:
第一个集合,即常规迭代器,可以指向任何元素,无论是设置还是未设置.如果它们被读取,它们将返回设置值,或者value_type(),如果它们被写入,则它们创建元素并返回左值引用.因此,它们是:
随机访问遍历迭代器和可读和可写迭代器
第二个集合,即稀疏迭代器,仅迭代set元素.由于他们不需要懒惰地创建写入的元素,因此它们是:
随机访问遍历迭代器和可读和可写和左值迭代器
我还需要两者的const版本,这些版本都是不可写的.
我可以填写空白,但不知道如何使用boost :: iterator_adaptor开始.
这是我到目前为止所拥有的:
template<typename T>
class sparse_vector {
public:
typedef size_t size_type;
typedef T value_type;
private:
typedef T& true_reference;
typedef const T* const_pointer;
typedef sparse_vector<T> self_type;
struct ElementType {
ElementType(size_type i, T const& t): index(i), value(t) {}
ElementType(size_type i, T&& t): index(i), value(t) {}
ElementType(size_type i): index(i) {}
ElementType(ElementType const&) = default;
size_type index; …Run Code Online (Sandbox Code Playgroud) 我一直在使用advance一些iterators,但恐怕上述可能的越级end().我想确保我的迭代器保持在界限之间,我想到了distance但似乎它没有返回我期望的东西(迭代器超越时的非正值end()).你怎么能确保没有越级?
#include <iostream>
#include <iterator>
#include <list>
using namespace std;
int main () {
list<int> mylist;
for (int i=0; i<10; i++) mylist.push_back (i*10);
list<int>::const_iterator first = mylist.begin();
const list<int>::const_iterator last = mylist.end();
cout << "The distance is: " << distance(first,last) << endl; // 10
advance(first, 10);
cout << "The distance is: " << distance(first,last) << endl; // 0
advance(first, 1);
cout << "The distance is: " << distance(first,last) << endl; …Run Code Online (Sandbox Code Playgroud) 编辑:我有很多答案告诉我,我应该将删除分成另一个循环.也许我没有说清楚,但我在上一段中说过,我想找到一个解决方法.即保持当前的代码结构,但使用一些鲜为人知的C++ fu来使其工作.
好吧,我知道调用erase()一个向量会使元素的迭代器和它之后的所有迭代器失效,并且erase()会将迭代器返回到下一个有效的迭代器,但是如果擦除发生在其他地方呢?
我有以下情况(简化):
警告:不要认为这是整个代码.下面显示的内容非常简单,以说明我的问题.下面显示的所有类和方法实际上要复杂得多.
class Child {
Parent *parent;
}
class Parent {
vector<Child*> child;
}
void Parent::erase(Child* a) {
// find an iterator, it, that points to Child* a
child.erase(it);
}
int Child::update() {
if(x()) parent.erase(*this) // Sometimes it will; sometimes (most) it won't
return y;
}
void Parent::update() {
int i = 0;
for(vector<A>::iterator it = child.begin(); it != child.end(); it++)
i += (*it)->update();
}
Run Code Online (Sandbox Code Playgroud)
因此,很明显,(*it)->update()如果x()返回true ,它会在运行后崩溃,因为当它执行时,Child会告诉Parent将它从向量中移除,使迭代器无效.
有没有什么方法可以解决这个问题,而不是让Parent::erase() …
int *arr = (int*) malloc(100*sizeof(int));
int *arr_copy = (int*) malloc(100*sizeof(int));
srand(123456789L);
for( int i = 0; i < 100; i++) {
arr[i] = rand();
arr_copy[i] = arr[i];
}
// ------ do stuff with arr ------
// reset arr...
std::copy(arr_copy, arr_copy+100, arr);
Run Code Online (Sandbox Code Playgroud)
在编译时,我得到以下警告std::copy():
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xutility(2227):
warning C4996: 'std::_Copy_impl': Function call with parameters that may be
unsafe - this call relies on the caller to check that the passed values are
correct. To disable this warning, …Run Code Online (Sandbox Code Playgroud) 我试图编写一些代码来进行序列的功能式创建.我编写了一个函数,range(a, b)它返回一个可以迭代的对象,foreach-style,遍历数字a,a + 1,...,b - 1.然后我写了另一个函数map(f, t),它返回另一个函数对象,其中序列中的每个元素都是f使用可迭代对象的相应元素进行调用的结果t.
如果我使用-O1或更低编译,这可以按预期工作; 有了-O2或更高,我的foreach循环(在main底部)得到完全优化,没有任何打印.为什么会这样,我做错了什么?这是我的代码:
template<typename T>
struct _range {
T a;
T b;
_range(T a, T b):
a(a),
b(b)
{
}
struct iterator {
T it;
iterator(T it):
it(it)
{
}
bool operator!=(const iterator &other) const
{
return it != other.it;
}
void operator++()
{
++it;
}
T operator*() const
{
return it;
}
};
iterator begin() const
{
return iterator(a); …Run Code Online (Sandbox Code Playgroud) 我有一个枚举器类型:
enum PlayerProps {
Attempts;
Gold;
Diamonds;
}
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能遍历所有枚举值?就像是:
var props = new Map<PlayerProps, Int>();
for (prop in PlayerProps)
props[prop] = 0;
Run Code Online (Sandbox Code Playgroud) 我试图理解迭代器.我注意到Python文档认为迭代器是一个功能样式的构造.我真的不明白.
迭代器里面有一个状态是不是真的.所以当你调用时it.__next__(),你会改变迭代器的状态.据我所知,对象的变异状态不被认为是功能性的,因为函数式编程强调对象/闭包的不变性和组合能力.
实际上,问题出现了,因为我想编写一个Scheme过程/函数,它接受令牌并返回一个迭代器.
(define tokens->iterator
(lambda ls
(lambda ()
(if (null? ls)
'*eoi*
(let ((tok (car ls)))
(set! ls (cdr ls))
tok)))))
Run Code Online (Sandbox Code Playgroud)
请注意我必须使用set!变异ls,这就是我提出这个问题的方法.
要使用它,
(define it (tokens->iterator 1 '+ 2))
Run Code Online (Sandbox Code Playgroud)
要测试它,
scheme@(guile-user)> (it)
$2 = 1
scheme@(guile-user)> (it)
$3 = +
scheme@(guile-user)> (it)
$4 = 2
scheme@(guile-user)> (it)
$5 = *eoi*
scheme@(guile-user)> (it)
$6 = *eoi*
Run Code Online (Sandbox Code Playgroud)
只是为了好玩,我还将其翻译成Python:
def tokens_to_iterator(*tup):
ls = list(tup)
def iterator():
if not ls:
return "*eoi*"
else:
tok = …Run Code Online (Sandbox Code Playgroud) #include <vector>
#include <iostream>
#include <range/v3/all.hpp>
int main()
{
auto coll = std::vector{ 1, 2, 3 };
ranges::copy(
coll,
ranges::ostream_iterator<int>{ std::cout, ", " }
); // ok
ranges::copy(
coll,
std::ostream_iterator<int>{ std::cout, ", " }
); // error
}
Run Code Online (Sandbox Code Playgroud)
问题显示在上面的代码中.我使用range-v3-0.3.7.
对我来说,通用算法copy不应该关心目标迭代器类型,只要它满足输出迭代器的要求即可.
如果是这样,为什么范围的算法不与std的迭代器兼容?