在标题中是否可以将多个数组连接在一起而无需复制并仅使用指针?我花费了大量的计算时间将较小的数组复制到较大的数组中。 注意我不能使用向量,因为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;
}
注意:我已经知道了一个简单的解决方案,只是将它们迭代地复制到一个新的大型数组中,但很高兴知道是否不需要复制在整个持续时间内存储的重复块。程序。我正处于学习曲线中。
感谢阅读所有人
答案 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
保证其内容的存储始终是连续的。
但是,当insert
或erase
来自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
答案 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);
}