从一个数组选择性地浅复制到另一个数组

6
假设我有两个不同大小的数组,即:
int arr[] = {0,1,2,3,4,5,6,7,8,9};
int *arr2 = new int[5];

我想要浅拷贝其中一些, 深拷贝的等价方法为:
int j =0;    
if(!(i%2))
    {
        arr2[j]=arr[i];
        j++;
    }

现在,打印arr2的结果是:0,2,4,6,8。

我想要浅拷贝的原因是,我希望arr2能随着arr的任何更改而更新。

也就是说,如果我循环并平方arr中的所有元素

我希望arr2输出:0、4、16、36、64

这两个数组是同一个类的一部分,其中一个是我的多边形信息,另一个是数据驱动的。arr实际上有4000多个元素,而arr2则接近3000个。目前,我的算法使用深拷贝效果很好。但是,因为我每次更新帧需要深拷贝3000个元素,我正在浪费资源,并且想知道是否可以通过浅拷贝来完成这项工作,以便我不必每帧都更新arr2。我的代码需要这样工作,arr实际上具有arr2的重复值。arr2是一个点列表,可以进行动画处理。然后将数据复制到arr中,该数组保存顶点的位置数据。这是因为arr包含多个bezier路径,其中一些与另一个路径共享一个或多个边缘。但是我希望在动画处理时忽略它,否则表面会出现断裂。

重要的是,复制涉及索引,例如

arr2[j]=arr[i];

因为这是我的代码设置方式。 而且操作需要低负载。


1
对于C++解决方案,您应该编写一个类似于std::array的类,其中包含operator[],可以正确引用原始内容。有点像模型-视图的东西。 - hyde
@hyde 一个类仍然会在内部执行深拷贝,这会导致性能问题。 - new2code
@MattMcNabb 是的,有这样的情况。arr是比arr2更大的数组。所以如果我执行*arr2 = arr; 我会丢失数据。而棘手的部分是arr包含了按特定顺序从arr2中重复的数据。 - new2code
@hyde 他们之间的数据关系非常复杂。我正在将4*4个3D点片拼接在边缘处,而且有数百个这样的点片。每个帧我都会对较小的集合进行更改(动画效果),这已经是30,000多个赋值操作,更不用说所有计算了。如果我要进行任何形式的赋值,我至少要做两次以上。这必须在1000个CPU时钟周期中完成60次。这就是为什么我想尽可能避免复制它。我宁愿有一个指向该集合的指针数组,就像Krypton在下面建议的那样。 - new2code
既然你还在谈论复制,我写了一个答案来演示我的意思(注意,不是复制!)。无论如何,要知道哪个更快,唯一的方法就是进行基准测试(开启编译器优化),但指针数组方法的额外内存访问肯定不便宜。 - hyde
显示剩余4条评论
3个回答

6

您需要一个整型指针数组来实现这个功能。

int *arr2[5];

for (int i = 0, j = 0; i < 10; i++) {
    if (!(i%2)) {
        arr2[j]= &arr[i];
        j++;
    }
}

因此,您需要通过 arr2[j]= &arr[i]; 将 arr2 的每个元素设置为指向 arr 中相应元素的指针。

当您需要访问 arr2 中的元素时,可以像这样调用:int a = *arr2[j];

稍后,假设您将 arr[0] 更改为 10 arr[0] = 10; 那么 int a = *arr2[0]; 将给您 10。


应该使用 sizeof(arr) / sizeof(*arr)...(或者如果arr是一个std::array,则更直观的是arr.size())。 - Jarod42
我明白了,所以我用指针数组代替了数组。因此,当我需要值时,我只需对它们进行解引用即可。这非常有道理。不过,我有一个问题,有没有办法新建一个整型指针数组?我不确定语法。 - new2code
我需要动态分配arr2。我尝试了new int[5]和new int[5],但似乎不正确。最坏的情况是我会让arr2比它需要的大得多,并使用另一个变量来跟踪其可用大小。但我宁愿不这样做。顺便说一下,谢谢你的答案,你极大地提高了我的帧率。 - new2code
1
没关系,我已经想通了,我需要 int *arr2 = new int[5]。感谢你的帮助。 - new2code
很高兴听到你解决了问题。学习C/C++非常有趣,你会在学习的过程中上瘾。 - Krypton

0
作为指针数组方法的替代方案,这里提供了一个简单的 C++03 示例,展示如何以编程方式实现。哪种方法更好取决于实际使用情况中 operator[] 的复杂程度以及第二个数组的大小(即需要多少额外内存,导致缓存未命中等)。
#include <iostream>

class c_array_view  {
public:
    c_array_view(int *array) : array_(array) {}
    int& operator[](size_t index) { return array_[index*2]; }

    static size_t convert_length(size_t original) { return original / 2; }

private:
    int *array_;
};

int main()
{
    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    size_t arr_len = sizeof arr / sizeof arr[0];

    c_array_view arr2(arr);
    size_t arr2_len = arr2.convert_length(arr_len);

    for(unsigned i = 0; i < arr_len; ++i) {
        std::cout << "arr: " << i << " = " << arr[i] << std::endl;
    }
    std::cout << std::endl;

    for(unsigned j = 0; j < arr2_len; ++j) {
        std::cout << "arr2: " << j << " = " << arr2[j] << std::endl;
    }
    std::cout << std::endl;

    arr2[2] = 42;
    std::cout << "modifeid arr2[2] to 42, now arr[4] = " << arr[4] << std::endl;

    return 0;
}

c_array_view 可以转换为一个模板,一个很好的通用类,它将采用 C++11 lambda 作为映射函数等,这只是演示原理。


-2
如果你想要平方,那么你不应该这样做:arr2[j]=arr[i]。正确的答案应该是:
arr2[j]=arr[i]*arr[i];

OP希望arr2引用arr。平方只是一个例子。 - juanchopanza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接