我的问题很简单:std :: vector元素是否保证是连续的?顺便说一句,我可以将指向std :: vector的第一个元素的指针用作C数组吗?

如果我的记忆很好,那么C ++标准并不能保证。但是,由于std :: vector要求如此,如果元素不连续,则几乎不可能满足它们。

有人可以澄清吗?

示例:

std::vector<int> values;
// ... fill up values

if( !values.empty() )
{
    int *array = &values[0];
    for( int i = 0; i < values.size(); ++i )
    {
        int v = array[i];
        // do something with 'v'
    }
}


评论

我知道,如果对if块中的值进行突变会给您带来麻烦。不过,我不知道您问题的答案,因此,我只想发表评论。 :)

@Greg:什么麻烦–您能详细说明一下吗?

我想他的意思是推新值可能会触发“重新分配”,这将导致数组变为无效。

改变值的调用,特别是改变其大小的调用(例如push_back()),可能会提示重新分配底层向量,从而使复制到数组中的指针无效。使用vector :: iterator而不是指向vector的指针背后的原理相同。 :)

是的,我将``''值放在周围以试图弄清楚我是在谈论类本身,而不是其中包含的值。 :)不幸的命名等等。在一般情况下,尽管这个问题是相关的,但我不认为这确实是一个问题-为什么有人会抓住指向内存的指针,然后开始使用向量进行处理而不是使用指针?傻。

#1 楼

适当的C ++ 98标准缺少此功能,但后来将其添加为TR的一部分。当然,即将到来的C ++ 0x标准也将包含此要求。类模板向量[vector]

1向量是支持随机访问迭代器的序列容器。此外,它还支持(摊销)
最后的恒定时间插入和擦除操作;在中间插入和擦除需要线性时间。存储
管理是自动处理的,尽管可以提供一些提示以提高效率。
向量的元素是连续存储的,这意味着如果v是一个向量,其中T是bool以外的其他类型,则它服从&v [n] ==&v [0] + n对于所有0 <= n

评论


ISO 14882,第2版,第23.2.4节[lib.vector]中也对此进行了说明:“向量的元素是连续存储的,这意味着如果v是vector ,其中T是除bool,那么对于所有0 <= n
–迈克·卡隆(Mike Caron)
09年5月11日在17:52

所以s,TR,TC,:)实际上,从我读到的内容来看,C ++ 03也被称为C ++ 98-TC1(技术勘误)

– Johannes Schaub-小人
09年5月11日在18:02

向量的向量呢? İnner向量在最后一组的内部向量之后吗?

–huseyin tugrul buyukisik
16年4月4日在20:04

@huseyin tugrul buyukisik您是否已了解答案?我也想知道这是如何工作的

–大卫·多里亚(David Doria)
16-10-27在21:10

@huseyin tugrul buyukisik当然是对的,但是后续的std :: vector实例是连续的。例如:instd :: vector > v元素v [0],v [1],...随后存储在内存中,但是元素v [0] .back()和v [1] .front()不保证是。

– jarzec
17年11月24日10:36



#2 楼

正如其他答案所指出的那样,向量的内容保证是连续的(布尔的怪异除外)。

我想添加的注释是,如果您在向量,这可能导致向量重新分配其内存,然后您将使所有保存的指针和迭代器失效。

评论


元素仍将存储在连续的存储块中,只是位于不同的位置。问题特别是关于连续性。

–迪马
09年5月11日在17:52

但是现有的指针和迭代器将失效。

–比尔·林奇
09年5月11日在18:49

好点子。您应该将其放入答案中以阐明您的意思。

–迪马
09年5月13日在22:33

对我最有用的答案

–CoffeDeveloper
13年4月22日在9:42

现在我知道为什么昨天我的程序出现段错误了,当我在一个双循环中循环删除了某些元素时:)谢谢!

–user2891462
15年7月30日在15:29

#3 楼

实际上,该标准确实保证了vector在内存中是连续的,并且可以将&a[0]传递给需要数组的C函数。

该规则的例外是vector<bool>,每个bool仅使用一位因此,尽管它确实具有连续的内存,但不能用作bool*(这被广泛认为是错误的优化和错误)。

顺便说一句,为什么不使用迭代器?那就是他们的目的。

评论


>顺便说一句,为什么不使用迭代器?那就是他们的目的。也许他阅读了有关该主题的Alexanrescu的新论文:boostcon.com/site-media/var/sphene/sphwiki/attachment/2009/05/…

– Nemanja Trifunovic
09年5月11日在18:06

感谢您的链接,我将其链接至我的阅读列表(我尽量不要错过Alexandresu的文章)

–莫蒂
09年5月11日在18:22

夸哈哈,这些天似乎每个人都在谈论那个演讲。您看,关于它的讨论仍然很热门:groups.google.com/group/comp.lang.c ++。moderated / browse_thread / ...

– Johannes Schaub-小人
09年5月11日在18:25

如果仔细阅读,Alexandrescu的文章实际上并不会说“不要在C ++中使用迭代器”,而是说“签出D”。他在该论文中描述的方法与吸收功能继承的任何现有语言和框架都非常相似(List,Scheme,Haskell),我严重怀疑另一种基于C的语法是否是更好地实现这一目标的理想起点列表处理。去年的某个时候,我曾短暂地试图说服他,将他的才华转化为改进像C#这样已经建立的语言,但是我担心没有成功! :)

–丹尼尔(Daniel Earwicker)
2010-2-18在8:23

#4 楼

正如其他人已经说过的那样,vector在内部使用了连续的对象数组。每当将任何非const成员函数称为IIRC时,都应将指向该数组的指针视为无效。

但是有一个例外!!

vector<bool>具有专门设计的实现以节省空间,以便每个布尔仅使用一位。基础数组不是布尔数组的连续数组,并且vector<bool>上的数组算法无法像vector<T>那样工作。

(我想向量的任何特殊化都可能是正确的,因为我们总是可以实现一种新的方法。但是,std::vector<bool>是唯一的,错误的,标准的专业知识,无法在其上执行简单的指针算法。)

评论


不允许用户专门使用std :: vector,并且要求所有其他向量使用连续存储。因此,(很幸运)std :: vector 是唯一奇怪的标准向量。 (我强烈认为,不建议使用此专业化功能,而应使用功能大致相同的std :: dynamic_bitset代替。这不是坏的数据结构,也不是矢量。)

– Arne Vogel
17年9月22日在9:57

#5 楼

我找到该线程是因为我有一个用例,其中使用连续内存的向量是一个优势。

我正在学习如何在OpenGL中使用顶点缓冲区对象。我创建了一个包装类来包含缓冲区逻辑,因此我要做的就是传递一个浮点数数组和一些配置值来创建缓冲区。
我希望能够从基于函数的函数中生成缓冲区根据用户输入,因此长度在编译时未知。这样做是最简单的解决方案:现在,我可以将向量的浮点作为数组传递给OpenGL的与缓冲区相关的函数。这样也就不需要用sizeof来确定数组的长度了。

比分配一个巨大的数组来存储float并希望我做得足够大,或者制作自己的动态数组要好得多。具有连续存储。

评论


这个功能对我来说没有任何意义。您的意思是传递给v的引用或指针,而不是v本身?因为单独传递v会导致在函数内部创建一个副本,该副本在函数结束后将不复存在。因此,您将某些内容推到向量上只是为了在函数结束时删除向量。

–约翰贝克斯
13年4月5日,0:31

#6 楼

cplusplus.com:向量容器以动态数组的形式实现;与常规数组一样,向量容器将其元素存储在连续的存储位置中,这意味着它们的元素不仅可以使用迭代器进行访问,还可以使用常规指向元素的偏移量来访问。


#7 楼

是的,保证std :: vector的元素是连续的。

评论


对。我想我用的太多了:)

–贝诺
09年5月11日在18:23