3参数形式list::splice()将单个元素从一个列表移动到另一个列表. SGI的文档明确声明所有迭代器,包括指向要移动的元素的迭代器仍然有效. Roguewave的文档没有说明splice()方法的迭代器失效属性,而C++标准明确声明它使所有迭代器和对被拼接元素的引用无效.
splicing()在实践中按照SGI的定义工作,但是我在微软的STL实现的调试/安全SCL版本中得到断言失败(解除引用无效迭代器)(严格遵循标准的字母).
现在,我正在使用list完全是因为我想在列表之间移动一个元素,同时保留指向它的迭代器的有效性.该标准对最初的SGI规范进行了极为无益的改变.
我该如何解决这个问题?或者我应该是务实,在沙把头(因为拼接并没有在实践中迭代器失效-甚至在MS的执行,一旦调试迭代器关闭).
假设我有以下课程:
public class Foo {
private List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
private Iterator<Integer> iterator = Iterators.cycle(list);
public void bar(){
Integer value = iterator.next();
doSomethingWithAnInteger(value);
}
}
Run Code Online (Sandbox Code Playgroud)
如果一个Foo实例被两个线程同时访问,我需要每个线程从中获取不同的值iterator.next().该bar()方法是否必须同步?或者iterator.next()保证是线程安全的?
在这个例子中,我使用ArrayList作为底层的Iterable.循环迭代器的线程安全性是否依赖于特定的可迭代实现?
谢谢.
鉴于:
val list = List("one","two","three")
val it = list.toIterator
Run Code Online (Sandbox Code Playgroud)
我可以跑:
list map ("_" +) -> List(_one, _two, _three)
for (i <- list) yield("_" + i) -> List(_one, _two, _three)
Run Code Online (Sandbox Code Playgroud)
如果我在迭代器上运行相同的操作,我得到:
it map ("_" + ) -> Iterator[java.lang.String] = empty iterator
for (i <- it) yield("_" + i) -> Iterator[java.lang.String] = empty iterator
Run Code Online (Sandbox Code Playgroud)
在我运行map/for之后,我不应该再找回另一个(非空的)Iterator [String]吗?
我想知道使std::list<>::splice引用新子容器中的子序列的迭代器无效的原因是什么.这看起来有点不合逻辑,特别是在标准std::container::swap规格方面.根据语言标准std::container::swap 不会使任何迭代器无效.这是一个非常合理的实用规范.但是,我会说这std::list<>::splice也会从保留迭代器的行为中获益匪浅.
我理解可能存在基于迭代器可达性等概念的纯粹学术考虑.但同时splice也是一种std::list特定的操作,这意味着为它提供定制的规范可能不会对其造成严重的概念损害.一般的STL设计.
那是什么?它会使一些std::list我认识不到的实际实施变得非法或过于复杂吗?
受这个问题的启发,询问如何将一个向量附加到自身,我的第一个想法是以下(是的,我意识到insert现在是一个更好的选择):
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> vec {1, 2, 3};
std::copy (std::begin (vec), std::end (vec), std::back_inserter (vec));
for (const auto &v : vec)
std::cout << v << ' ';
}
Run Code Online (Sandbox Code Playgroud)
但是,这打印:
1 2 3 1 * 3
Run Code Online (Sandbox Code Playgroud)
每次运行程序时*都是不同的数字.只有2被替换的事实是特殊的,如果真的有解释,我会有兴趣听到它.继续,如果我附加到不同的向量(原始副本),它会正确输出.如果我在前一行之前添加以下行,它也会正确输出copy:
vec.reserve (2 * vec.size());
Run Code Online (Sandbox Code Playgroud)
std::back_inserter尽管事先没有预留内存,但我认为这是一种将元素添加到容器末端的安全方法.如果我的理解是正确的,复制线有什么问题?
我假设它与编译器无关,但我使用的是GCC 4.7.1.
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) 我正在尝试编写一个is_iterator<T>类型特征.凡当T是一个迭代器类型is_iterator<T>::value == true,否则是is_iterator<T>::value == false.
到目前为止我尝试了什么:
template <class, class Enable = void>
struct is_iterator : std::false_type {};
template <typename T>
struct is_iterator<T, typename std::enable_if<std::is_pointer<typename
std::iterator_traits<T>::pointer>::value>::type> : std::true_type {};
Run Code Online (Sandbox Code Playgroud)
问:是否有更合适的方式来定义is_iterator类型特征而不是上面显示的类型特征?
我试图理解迭代器.我注意到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) ->*如果重载->,显然不能自动工作,并且必须手动重载.
为什么标准容器迭代器不超载->*除了->,迫使使用(*iter).*mem_ptr代替iter->*mem_ptr?
#include <iostream>
#include <vector>
struct S
{
int x;
};
int main()
{
std::vector<S> vec = {{42}};
auto mem_ptr = &S::x;
std::cout << (*vec.begin()).*mem_ptr << '\n'; // This line compiles.
std::cout << vec.begin()->*mem_ptr << '\n'; // This line doesn't compile.
}
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的迭代器兼容?
iterator ×10
c++ ×7
stl ×3
algorithm ×1
c++-concepts ×1
c++11 ×1
c++14 ×1
c++20 ×1
containers ×1
for-loop ×1
guava ×1
invalidation ×1
java ×1
list ×1
map ×1
python ×1
range-v3 ×1
scala ×1
scheme ×1
type-traits ×1