在Herb Sutter中When Is a Container Not a Container?,他展示了一个将指针放入容器的示例:
// Example 1: Is this code valid? safe? good?
//
vector<char> v;
// ...
char* p = &v[0];
// ... do something with *p ...
Run Code Online (Sandbox Code Playgroud)
然后跟着它"改进":
// Example 1(b): An improvement
// (when it's possible)
//
vector<char> v;
// ...
vector<char>::iterator i = v.begin();
// ... do something with *i ...
Run Code Online (Sandbox Code Playgroud)
但实际上并没有提供令人信服的论据:
一般来说,当你想指向一个容器内的对象时,更喜欢使用迭代器而不是指针并不是一个糟糕的指导.毕竟,迭代器在与指针大致相同的时间和相同的方式上无效,并且迭代器存在的一个原因是提供一种"指向"包含对象的方法.因此,如果您有选择,请更喜欢将迭代器用于容器中.
不幸的是,你不能总是得到与迭代器相同的效果,你可以使用指针到容器.迭代器方法有两个主要的潜在缺点,当适用时我们必须继续使用指针:
您不能总是方便地使用可以使用指针的迭代器.(见下面的例子.)
在迭代器是一个对象而不仅仅是一个光头指针的情况下,使用迭代器可能会产生额外的空间和性能开销.
在向量的情况下,迭代器只是一个RandomAccessIterator.对于所有意图和目的,这是指针上的薄包装.一种实现甚至承认这一点:
// This iterator adapter is 'normal' in the sense that it does not …Run Code Online (Sandbox Code Playgroud) 我有以下关于 C++20 中的 range 库的问题:
让std::ranges::contiguous_range<T>一个任意类型T.
我可以假设std::ranges::sized_range<T>吗?
考虑:
#include <map>
int main()
{
std::map< int, int > m;
m[ 0 ] = 0;
m[ 1 ] = 1;
m.erase( 0 ); // ok
m.erase( 2 ); // no-op
m.erase( m.find( 2 ) ); // boom!
}
Run Code Online (Sandbox Code Playgroud)
(好的,所以标题讨论了擦除end()迭代器,但是find会返回end()以查找不存在的键.)
为什么擦除不存在的键OK,但擦除end()会爆炸.我在标准中没有看到任何明确的提及?
我在VS2005上尝试了这个(在调试配置中抛出异常)和GCC 4.0.1(100%CPU).它是依赖于实现的吗?
谢谢.
我在django.template中有以下代码:
class Template(object):
def __init__(self, template_string, origin=None, name='<Unknown Template>'):
try:
template_string = smart_unicode(template_string)
except UnicodeDecodeError:
raise TemplateEncodingError("Templates can only be constructed from unicode or UTF-8 strings.")
if settings.TEMPLATE_DEBUG and origin is None:
origin = StringOrigin(template_string)
self.nodelist = compile_string(template_string, origin)
self.name = name
def __iter__(self):
for node in self.nodelist:
for subnode in node:
yield subnode
def render(self, context):
"Display stage -- can be called many times"
return self.nodelist.render(context)
Run Code Online (Sandbox Code Playgroud)
我困惑的部分如下.这种__iter__方法有什么用?我找不到任何相应的next方法.
def __iter__(self):
for node in self.nodelist:
for subnode …Run Code Online (Sandbox Code Playgroud) 鉴于此代码,是否可以更改dumpStrings()为能够迭代任何容器string,比如说list<string>?
#include <vector>
#include <string>
#include <ostream>
#include <iostream>
using namespace std;
void dumpStrings(vector<string>::iterator it, vector<string>::iterator end)
{
while (it != end) {
cout << *it++ << endl;
}
}
int main()
{
vector<string> strVector;
strVector.push_back("Hello");
strVector.push_back("World");
dumpStrings(strVector.begin(), strVector.end());
return 0;
}
Run Code Online (Sandbox Code Playgroud) 按范围我的意思是一对迭代器.在伪C++中:
std::vector<int> v1 = { 1, 2, 3, 4, 5 };
std::vector<int> v2 = { 2, 3, 4 };
if( std::compare_range( v1.begin() + 1, v1.end() - 1, v2.begin(), v2.end() ) {
std::cout << "Alright\n";
}
Run Code Online (Sandbox Code Playgroud)
compare_range 当然是我正在寻找的功能.
免责声明:我知道,这是一个非常简单的写作功能.但像所有程序员一样,我试图变得懒惰;-)
如果元素std::initializer_list总是const值,为什么我们有模板方法喜欢begin()/end()和不cbegin()/cend()?这个名称(通过惯例,与例如比较std::vector)可以表明,当它们总是返回时,两种std::initializer_list方法都可以iterator返回const_iterator.
考虑接受一个或多个参数(例如文件名)的函数.为了使其具有通用性,将其编写为通用迭代器范围是有利的:
template<class Iter>
void function(Iter first, Iter last)
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以通过以下方式调用它,与我们存储参数的方式无关:
WhateverContainer container;
function(std::begin(container), std::end(container));
Run Code Online (Sandbox Code Playgroud)
例如,STL在很大程度上依赖于这种范例.
现在,假设我们想要使用未存储在容器中的单个参数来调用该函数.我们当然可以写:
const int value = 5;
std::vector<int> vec(1, value);
function(std::begin(vec), std::end(vec));
Run Code Online (Sandbox Code Playgroud)
但这个解决方案对我来说似乎很笨拙和浪费.
问题:是否有更好的低开销方法来创建单个变量的迭代器范围兼容表示?