将数组写入向量时避免复制

时间:2013-10-23 22:47:40

标签: c++

但是如果你想阻止5000副本(或更多)的一些可能丑陋的重物。只是为了提高性能而忽略可读代码,你可以这样做

#include <iostream>
#include <vector>

int main(int argc, char* argv[])
{
    std::vector<int> v;
    int* a = (int*) malloc(10*sizeof(int));
    //int a[10];
    for( int i = 0; i<10;++i )
    {
        *(a + i) = i;
    }

    delete v._Myfirst; // ? not sure
    v._Myfirst = a;

    for( int i = 0; i<10;++i )
    {
        std::cout << v[i] << std::endl;
    }

    system("PAUSE");

    return 0;
}

只需替换_Myfirst底层“数组”。但要非常小心,这将被矢量删除。

  1. 在某些情况下,我的删除/免费首次失败吗?
  2. 这取决于分配器吗?
  3. 是否有交换?有一个全新的矢量交换,但是如何从数组?
  4. 我必须与我无法修改的代码(政治原因)接口,它为我提供了对象数组,并且必须使它们成为对象的向量。

    指针似乎是正确的解决方案,但是它有很多内存跳转,我还是要执行循环。我只是想知道是否有某种方法可以避免副本并告诉向量,“现在这是你的底层数组”。

    我同意以上内容非常难看,这就是为什么我实际上保留并推送我的真实代码。我只是想知道是否有办法避免循环。

    请不要回答循环和推回,显然这就是我的“真实”代码已经在做的事情。如果没有执行此交换的功能,我们可以实现一个安全的吗?

3 个答案:

答案 0 :(得分:6)

  

问题1:在某些情况下,我的删除/免费首次失败吗?

是。您不知道如何分配_Myfirst的内存(除了它使用分配器)。该标准没有规定默认分配器应该使用malloc来分配内存,因此您不知道delete是否有效。

此外,您正在混合分配方案。

您正在使用malloc()进行分配。但期望std::vector<>分配new(因为您正在调用删除)。

即使分配器确实使用了new,它也可能是new的数组版本,因此你需要使用delete的数组版本来回收内存。

  

问题2:这取决于分配器吗?

  

问题3:是否存在交换?有一个全新的矢量交换,但来自一个数组?

没有

防止昂贵的副本。使用emplace_back()

std::vector<int> v;
v.reserve(10);            // reserve space for 10 objects (min).

for( int i = 0; i<10;++i )
{
    v.emplace_back(i);   // construct in place in the array (no copy).
}

答案 1 :(得分:0)

如果您不喜欢矢量的行为方式,请不要使用矢量。您的代码取决于您不能依赖的实现细节。

是的,你说的很难看。使用正确的容器使其漂亮。

您使用的容器取决于容器上需要的操作。它可能就像C风格的阵列一样简单,可以满足您的需求。如果您希望向量管理HeavyObjects的生命周期,它可能是指针或共享指针的向量。


为了满足增加收藏规模的需要(见下面的评论):

std :: vector保证底层存储是连续的,因此如果增加大小,它将分配一个新的更大的缓冲区并将旧的缓冲区复制到新的缓冲区中(如果存在对象,则使用对象的复制构造函数。)然后将新缓冲区交换到位 - 使用自己的分配器释放旧缓冲区。

除非你强制进入向量的缓冲区以与向量分配器一致的方式分配,否则这将丢弃你的内存。

因此,如果您的原始数组足够大,您只需要一个“maxUsed”size_t来告诉您该集合的大小以及放置新条目的位置。如果它不够大,那么你的技术要么会失败,要么会产生你想要避免的复制成本。

答案 2 :(得分:0)

std::vector<SomeUglyHeavyObject*> vect(5000, NULL);
for (int i=0; i<5000; i++)
{
    vect[i] = &arr[i];
}

在那里,避免复制,不会弄乱std::vector内部。