是否可以交换结构数组(线性时间)?

时间:2012-02-11 18:45:36

标签: c++ pointers struct

我有一个小程序来计算彼此的行星力量。我的程序有两个结构数组,一个在迭代前保持位置和速度,另一个在迭代后保持它们的位置和速度。

在每次迭代结束时,我想将第二个数组中的值移动到第一个数组中,第二个数组可能变为垃圾(但需要指向我稍后可以写入的一些有效内存位置)。我以为我可以简单地切换数组,因为数组是指针,但编译器不会让我。

考虑这个例子:

typedef struct { int a; } Foo;

int main()
{
   Foo bar[8], baz[8];

   Foo *temp = baz;
   baz = bar;   //ISO C++ forbids the assignment of arrays
   bar = temp;  //incompatible types in assignment of Foo* to Foo[8]
}

这就是我想做的。它肯定比从1到N的for循环更快。

6 个答案:

答案 0 :(得分:5)

您应该考虑使用可以在固定时间内交换的std::vector

std::vector<Foo> bar(8), baz(8);

std::swap(bar, baz);

或者如果您不想这样做而是想手动管理内存,可以使用new[]获取指向免费存储上的数组的指针,并在需要交换时交换指针数组。

如果必须在堆栈上安装数组,那么在没有实际交换每个元素的情况下执行此操作的唯一方法是在堆栈上创建数组,而不是使用数组,使用指向数组的指针:

Foo bar[8], baz[8], *pbar = bar, *pbaz = baz;

// ...
// this code only using pbar and pbaz
// ...

// swap the pointers
std::swap(pbar, pbaz);

// ...
// use pbar and pbaz some more
// ...

答案 1 :(得分:2)

这是你出错的地方:

  

因为数组是一个指针

事实并非如此。数组衰减指向一个指针,但它们不是一回事。

但是,通过实际获取这些数组的指针,您可以轻松地在此处执行所需操作。

   Foo bar[8], baz[8];

   // load bar up with valid data
   Foo *data = bar;
   Foo *garbage = baz;

   // compute next step

   std::swap(data,garbage);

还要考虑使用std::array而不是原始数组(它具有与C ++中其他类型更一致的属性,并且比原始数组更不“特殊”)。然后,当您使用指向这些数组的指针时,数组的大小将不会像指向原始数组的指针那样被丢弃。

   std::array<Foo,8> bar, baz;

   std::array<Foo,8> *data = &bar;
   std::array<Foo,8> *garbage = &baz;

   // compute next step

   std::swap(data,garbage);

如果你需要动态大小的数组使用std::vector,那么你可以直接交换向量而不是交换指向向量的指针,因为交换向量将被实现以交换向量内的指针。

   std::vector<Foo> data, garbage;

   // compute next step

   std::swap(data,garbage);

答案 2 :(得分:0)

问题是你正在使用堆栈分配的数组。

当您说Foo bar[8];时,您正在为当前堆栈帧中的八个Foo结构创建空间。因此,你无法将其分配给其他东西的原因是它必须以某种方式移出框架,逃避内存管理并确定它应该具有的范围。

您想要一个动态分配的数组 - Foo* bar = new Foo[8];。完成后,delete[] bar;。这里的区别在于现在指针在堆栈上,但实际内容在堆上 - 因此您可以更改指针引用的位置,而不必担心移动实际指针本身。 / p>

另一种选择是使用具有复制构造函数的类operator=,例如std::vectorstd::liststd::deque

顺便提及,复制阵列内容的过程是线性时间。指针赋值是常量时间(O(1)),因为它与数组的大小无关 - 它总是一个移动指针的操作。

答案 3 :(得分:0)

您可以使用memcpy:

int main()
{
   Foo bar[8], baz[8], temp[8];

   memcpy(temp, baz, sizeof(Foo) * 8);
   memcpy(baz, bar, sizeof(Foo) * 8);
   memcpy(bar, temp, sizeof(Foo) * 8);
}

答案 4 :(得分:0)

您可以将数组声明为temps,并声明指针 - 您将使用该指针用于函数的其余部分。

可以轻松交换那些ponters。

int main()
{
   Foo temp1[8], temp2[8];
   Foo *bar = temp1, *baz = temp2;

   Foo *temp = baz;
   baz = bar;  //no problems now 
   bar = temp;  
}

答案 5 :(得分:0)

   Foo bar[8], baz[8];

然后

   Foo* arr1 = bar, arr2 = bax;

忘掉baz&amp; bar,仅适用于arr1arr2

交换:

  int* temp = arr1;
  arr1 = arr2;
  arr2 = temp;