C ++:将数组连接在一起 - 是否可以使用指针进行复制?

时间:2011-08-01 15:43:39

标签: c++ arrays pointers join

在标题中是否可以将多个数组连接在一起而无需复制并仅使用指针?我花费了大量的计算时间将较小的数组复制到较大的数组中。 注意我不能使用向量,因为umfpack(一些矩阵求解库)不允许我或我不知道如何。

举个例子:

int n = 5;

// dynamically allocate array with use of pointer

int *a = new int[n];


// define array pointed by *a as [1 2 3 4 5]

for(int i=0;i<n;i++) {
    a[i]=i+1;
}


// pointer to array of pointers ???  --> this does not work

int *large_a = new int[4];
for(int i=0;i<4;i++) {
    large_a[i] = a;
}

注意:我已经知道了一个简单的解决方案,只是将它们迭代地复制到一个新的大型数组中,但很高兴知道是否不需要复制在整个持续时间内存储的重复块。程序。我正处于学习曲线中。

感谢阅读所有人

6 个答案:

答案 0 :(得分:6)

  

如标题所示,可以将多个数组连接在一起而无需复制,只使用指针?

简而言之,没有。

指针只是内存中的地址 - 就像街道地址一样。你不能移动两个房子,只需复制他们的地址。你也不能通过改变他们的地址来搬家。更改地址不会移动房屋,它指向新房。

  

注意我不能使用向量,因为umfpack(一些矩阵求解库)不允许我或我不知道如何。

大多数情况下,您可以在需要数组时传递std::vector的第一个元素的地址。

std::vector a = {0, 1, 2}; // C++0x initialization
void c_fn_call(int*);
c_fn_call(&a[0]);

这是有效的,因为vector保证其内容的存储始终是连续的。

但是,当inserterase来自vector的元素时,会使来自它的指针和迭代器无效。如果已分配的存储必须更改大小,那么从获取元素地址获得的任何指针都不再指向vector

答案 1 :(得分:3)

没有。两个数组的内存不一定是连续的,所以没有复制就无法连接它们。并且数组元素必须位于连续的内存中......或者指针访问是不可能的。

答案 2 :(得分:0)

我可能会使用memcpy / memmove,它仍然会复制内存,但至少它已被编译器供应商优化和测试。

当然,“真正的”C ++方法是使用标准容器和迭代器。如果你的内存遍布各处,那么使用链表似乎更好,除非你要进行大量的随机访问操作。

另外,请记住,如果使用指针和动态分配的数组而不是标准容器,则更容易导致内存泄漏和其他问题。我知道有时你没有选择,只是说。

答案 3 :(得分:0)

如果你想连接数组而不复制元素,同时你想使用下标运算符即[]来访问元素,那么如果不写一个封装所有这些功能的类。

我用最少的考虑编写了下面的类,但它演示了基本的想法,如果你希望它具有当前没有的功能,你可以进一步编辑。应该没有什么错误,我没有写,只是为了让它看起来更短,但我相信你会理解代码,并相应地处理错误情况。

template<typename T>
class joinable_array
{
     std::vector<T*>     m_data;
     std::vector<size_t> m_size;
     size_t              m_allsize;
   public: 
       joinable_array() : m_allsize() { }
       joinable_array(T *a, size_t len) : m_allsize() { join(a,len);}
       void join(T *a, size_t len)
       {
           m_data.push_back(a);
           m_size.push_back(len);
           m_allsize += len;
       }
       T & operator[](size_t i)  
       {
            index ix = get_index(i);
            return m_data[ix.v][ix.i];
       }
       const T & operator[](size_t i) const
       {
            index ix = get_index(i);
            return m_data[ix.v][ix.i];
       }
       size_t size() const { return m_allsize; }
  private:
       struct index
       {
           size_t v;
           size_t i;
       };
       index get_index(size_t i) const
       {
          index ix = { 0,  i};
          for(auto it = m_size.begin(); it != m_size.end(); it++)
          {
                if ( ix.i >= *it ) { ix.i -= *it; ix.v++; }
                else break;
          }
          return ix;
       }
};

这是一个测试代码:

#define alen(a) sizeof(a)/sizeof(*a)

int main() {

        int a[] = {1,2,3,4,5,6};
        int b[] = {11,12,13,14,15,16,17,18};

        joinable_array<int> arr(a,alen(a));
        arr.join(b, alen(b));
        arr.join(a, alen(a)); //join it again!

        for(size_t i = 0 ; i < arr.size() ; i++ )
            std::cout << arr[i] << " ";
}

输出:

1 2 3 4 5 6 11 12 13 14 15 16 17 18 1 2 3 4 5 6 

在线演示:http://ideone.com/VRSJI

答案 4 :(得分:0)

  

必须声明指向指针的变量。   这是通过在其名称前放置一个额外的asterik来完成的。   因此,int **large_a = new int*[4];您的large_a会找到一个指针,而您已将其定义为指向int的指针。它应该被定义(声明)为指针变量的指针。正如int **large_a;就足够了。

答案 5 :(得分:0)

以下是如何正确地做到这一点:

template<class T, class K1, class K2>
class JoinArray {
    JoinArray(K1 &k1, K2 &k2) : k1(k1), k2(k2) { }
    T operator[](int i) const { int s = k1.size(); if (i < s) return k1.operator[](i); else return k2.operator[](i-s); }
    int size() const { return k1.size() + k2.size(); }
 private:
    K1 &k1;
    K2 &k2;
 };
 template<class T, class K1, class K2>
 JoinArray<T,K1,K2> join(K1 &k1, K2 &k2) { return JoinArray<T,K1,K2>(k1,k2); }

 template<class T>
 class NativeArray
 {
     NativeArray(T *ptr, int size) : ptr(ptr), size(size) { }
     T operator[](int i) const { return ptr[i]; }
     int size() const { return size; }
  private:
     T *ptr;
     int size;
  };

 int main() {
    int array[2] = { 0,1 };
    int array2[2] = { 2,3 };
    NativeArray<int> na(array, 2);
    NativeArray<int> na2(array2, 2);
    auto joinarray = join(na,na2);
}