C++ 指针与 std::vector:对长变量有任何影响吗?

Posted

技术标签:

【中文标题】C++ 指针与 std::vector:对长变量有任何影响吗?【英文标题】:C++ pointers vs std::vector: any implication for long size variables? 【发布时间】:2020-11-17 17:42:36 【问题描述】:

我有 C 背景,我正在用 C++ 重新编写一些旧代码... 在这个过程中,我开始使用 C++ Vectors,它非常好用!

向量能否很好地处理很长的数据流?例如,在音频应用中,加载一首 3 分钟的立体声歌曲需要将近 16M 的浮点数

float *stereoSong = NULL;
stereoSong = new floats[15787800];

不必用向量处理内存管理非常好,但我想知道 C++ 向量是否可以很好地处理大量数据

谢谢!

【问题讨论】:

std::vector 只是堆中的一个数组,具有大小和指向第一个元素的指针。我能想到的唯一性能问题是每次扩展时容量都会增加 2 倍。这可以通过std::vector::reserve 甚至std::vector::shrink_to_fit 来解决。 既然你已经知道C,你可以把它比作一个动态分配的数组。 您可能会惊讶地发现std::vector 只是一个指针和一个元素计数(以及一个额外的计数器)。结束。 我在这被毫不客气地关闭之前写了一个答案。这是一个 noddy 程序,它可以输出一个非常大的向量。 ideone.com/A6GmvQ。该代码甚至足够简单,不保留容量,但允许 std::vector 执行此操作。 @WewillSee 嗨。我刚刚注意到您的矢量版本pointer2[i]=pointer2[i] 中有一个错误。您已将指针 2 分配给自身。优化器忽略了整个循环。当我运行它时,尽管这不是科学测试,但矢量版本实际上更快一点! 【参考方案1】:

这是一个错误的比较。

首先,向量使用指针。他们必须。向量是使用动态分配为您提供数据项缓冲区的容器。你可以尝试“用指针”实现同样的东西,但你最终会在向量和更糟糕的向量版本之间得到某种东西。

因此,向量可以处理与new double[] 一样多的数据——也就是说,很多。

【讨论】:

【参考方案2】:

答案很大程度上取决于您的平台。 您说的是超过 150 MiB 的数据(double 在几乎所有现代平台上都是 8 个字节)。 此代码在“玩具”环境中没有问题 (https://ideone.com/A6GmvQ):

#include <iostream>
#include <vector>

void build(std::vector<double>& data, const size_t size)
    void* ptrdata.data();
    for(size_t i1;i<=size;++i)
        data.push_back(2*i);
        if(data.data()!=ptr)
            ptr=data.data();
            std::cout << i << ' ' << ptr << ' ' << data.capacity() << std::endl;
        
    


int main() 
    size_t size100000000L;
    
    std::cout << ((size*sizeof(double))/1024/1024) << " MiB" << std::endl;
    
    std::vector<double> data;
    
    build(data,size);
    
    double sum0;
    for(auto curr : data)
        sum+=curr;
    
    std::cout << sum << std::endl;
    return 0;

这段代码明知是愚蠢的,甚至没有尝试为值保留容量(这可以提供帮助),因为std::vector&lt;&gt; 无论如何都可以帮助解决这个问题。

在幕后,向量分配一个容量块,然后当向量的逻辑大小超过容量时重新分配另一个更大的容量。 代码“监视”内部表示并输出每次重新分配...

如果您将值作为流使用(听起来很可能是音频),那么有成员可以帮助您进行容量管理。

简短的回答是“试一试”。我已经将它提高到 100M 双倍,没有问题。

【讨论】:

【参考方案3】:

std::vectorand 公司。是我将 C 更改为 C++ 的原因之一。

它将所有管理样板从数组管理中取出。

当我需要调整数组分配的大小时,我必须执行以下操作

    分配新内存 复制元素 删除旧记忆

此外,所有生命周期管理都由 std::vector 处理,在生命周期结束时不再与 delete 搞混,这使得在一个函数中处理多个退出点变得更加容易。

【讨论】:

【参考方案4】:

由于实现的限制是std::vector::max_size。比如herestd::vector&lt;float&gt;::max_size()就是2305843009213693951

但是,由于实施的限制,这只是理论上的限制。很快你就会达到硬件的内存限制。

std::vector&lt;float&gt; 不使用(基本上)比动态 c 数组更多的内存。

【讨论】:

以上是关于C++ 指针与 std::vector:对长变量有任何影响吗?的主要内容,如果未能解决你的问题,请参考以下文章

参与 std::vector C++

通过线程共享指针的 std::vector

使用指针 C++ [关闭] 指示 Vector 的索引

c++中向量的指针运算

从 C++ std::vector 中删除元素

指向std :: vector和std :: list元素的指针