用c++从存在数组创建子数组的最佳方式是什么?

时间:2023-01-25 21:40:46

OK, I am trying to get a sub array from an existing array and I'm just not sure how to do it. In my example I have a very large array, but I want to create an array from the last 5 elements of the array.

好的,我正在尝试从一个已有的数组中获取一个子数组,我只是不知道怎么做。在我的例子中,我有一个非常大的数组,但是我想从数组的最后5个元素创建一个数组。

An example of what I am talking about would be:

我要讲的一个例子是:

int array1 = {1,2,3,...99,100};
int array2[5] = array1+95;

I know this isn't correct, but I am having some trouble getting it right. I want to get the elements 96 through 100 in array1 and put them into array2 but I don't want to copy the arrays. I just want array2 to start at the 96 element such that array1[96] and array2[0] would be pointing to the same location.

我知道这是不对的,但我做得不对。我想在array1中得到96到100的元素然后放到array2中但是我不想复制数组。我只想让array2从96个元素开始这样array1[96]和array2[0]就指向同一个位置。

8 个解决方案

#1


18  

for this:

:

"such that array1[96] and array2[0] would be pointing to the same location."

you can do:

你能做什么:

int *arr2 = arr1 + 96;
assert(arr2[0] == arr1[96] == 97);

#2


8  

A reference hack from a C programmer willing to subvert the type system to get what works:

来自一个C程序员的引用黑客,他想要破坏类型系统以得到有效的东西:

int (&array2)[5] = (int (&)[5])(*(array1 + 5));

Now array2 will be an array for all intents and purposes, and will be a sub-array of array1, and will even be passable to that famous C++ array_size template function. Though the best way to handle this hackery is to hide it with more hackery!

现在array2将是一个数组,用于所有目的和目的,它将是array1的子数组,甚至可以传递给著名的c++ array_size模板函数。虽然处理这种黑客行为的最好方法是用更多的黑客行为来隐藏它!

#define make_sub_array(type, arr, off, len) (type (&)[len])(*(arr + off));

int (&array2)[5] = make_sub_array(int, array1, 5, 5);

Nice. Terrible by some standards, but the end result a) looks pretty neat, b) does exactly what you want, c) is functionally identical to an actual array, and d) will also have the added bonus (or mis-feature) of being an identical reference to the original, so the two change together.

好了。从某些标准来看,这很糟糕,但是最终结果a)看起来很整洁,b)做了你想做的事情,c)功能上与实际的数组相同,d)也会有额外的好处(或错误的特性),即与原始的引用相同,所以两者一起变化。

UPDATE: If you prefer, a templated version (sort of):

更新:如果你喜欢,模板版本(差不多):

template <typename T, size_t M>
T (&_make_sub_array(T (&orig)[M], size_t o))[]
{
    return (T (&)[])(*(orig + o));
}
#define make_sub_array(type, array, n, o) (type (&)[n])_make_sub_array(array, o)

int (&array2)[5] = make_sub_array(int, array1, 5, 5);

We still have to pass the type. Since one of our arguments must be used as part the cast, we cannot cleanly (IMHO) avoid the macro. We could do this:

我们还得通过这个类型。由于我们的一个参数必须作为角色的一部分使用,我们不能干净地(IMHO)避免宏观。我们可以这样做:

template <typename T, size_t M, size_t N>
T (&make_sub_array(T (&orig)[M], size_t o))[N]
{
    return (T (&)[N])(*(orig + o));
}

int (&array2)[5] = make_sub_array<int, 15, 5>(array1, 5);

But the goal here is to make the calling code as clean as possible, and that call is a bit hairy. The pure-macro version probably has the least overhead and is probably the cleanest to implement in this case.

但是这里的目标是让调用代码尽可能的干净,这个调用有点麻烦。纯宏版本的开销可能最少,在这种情况下可能是最干净的实现。

#3


3  

For a completely different approach you could do something like.

对于完全不同的方法,你可以做一些类似的事情。

vector<int> v0(array1 + 95, array1 + 100);

or

vector<int> v1(array1, array1 + 100);
vector<int> v2(v1.begin() + 95, v1.end());

This would make a real copy of the elements of your vector.

这将是向量元素的真实拷贝。

#4


3  

You can use boost::iterator_range to represent "slices" of arrays/containers:

可以使用boost:::iterator_range表示数组/容器的“片”:

#include <iostream>
#include <boost/range.hpp>

int main()
{
    int array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    // Create a "proxy" of array[5..7]
    // The range implements the concept of a random sequence containter
    boost::iterator_range<int*> subarray(&array[5], &array[7]+1);

    // Output: 3 elements: 5 6 7
    std::cout << subarray.size() << " elements: "
              << subarray[0] << " "
              << subarray[1] << " "
              << subarray[2] << "\n";
}

Note that the iterator range "knows" about the size of the sub-array. It will even do bounds checking for you. You cannot get that functionality from a simple pointer.

注意,迭代器范围“知道”子数组的大小。它甚至可以帮你检查边界。您无法从一个简单的指针中获得该功能。

The usefulness of Boost.Range will become more apparent once you learn about STL containers and iterators.

提高的有效性。一旦您了解了STL容器和迭代器,范围将变得更加明显。

If you're into linear algebra, Boost.uBlas supports ranges and slices for its matrices and vectors.

如果你学的是线性代数,那就用Boost。uBlas支持其矩阵和向量的范围和切片。

#5


1  

In C++ you can use an int pointer as an int array, so getting the array2 to start at item 96 in array1 is easy, but there isn't any way to give array2 a size limit, so you can do this

在c++中,可以使用int指针作为int数组,因此在array1中让array2从第96项开始是很容易的,但是没有办法给array2一个大小限制,所以可以这样做

int array2[] = &array1[96];

int array2[]= &array1[96];

or this

或者这个

int *array2 = &array1[96];

but NOT this

但是不是这个

int array2[5] = &array1[96]; // this doesn't work.

On the other hand, C++ doesn't enforce array size limits anyway, so the only real loss is that you can't use sizeof to get the number of elements in array2.

另一方面,c++并没有强制数组大小的限制,所以唯一真正的损失是您不能使用sizeof来获取array2中的元素数量。

note: &array1[96] is the same thing as array+96

注意:&array1[96]与数组+96相同

edit: correction - int array[] = &array[96] isn't valid, you can only use [] as a synonym for * when declaring a function parameter list.

编辑:校正- int数组[]= &数组[96]是无效的,您只能在声明函数参数列表时使用[]作为*的同义词。

so this is allowed

这是被允许的

extern int foo(int array2[]);
foo (&array1[96]);

#6


0  

int array1[] = {1,2,3,...99,100};
int *array2 = &array1[96];

#7


0  

int arr[] = { 1, 2, 3, 4, 5};
int arr1[2];
copy(arr + 3, arr + 5, arr1);
for(int i = 0; i < 2; i++)
    cout << arr1[i] << endl;

The code is not safe if the boundaries are not handled properly.

如果边界处理不当,代码就不安全。

#8


0  

You said you don't want to copy the array, but get a pointer to the last five elements. You almost had it:

你说过你不想复制数组,但是你可以得到一个指向最后五个元素的指针。你几乎把它:

int array1[] = {1,2,3,...99,100};
int* array2  = &array1[95];

#1


18  

for this:

:

"such that array1[96] and array2[0] would be pointing to the same location."

you can do:

你能做什么:

int *arr2 = arr1 + 96;
assert(arr2[0] == arr1[96] == 97);

#2


8  

A reference hack from a C programmer willing to subvert the type system to get what works:

来自一个C程序员的引用黑客,他想要破坏类型系统以得到有效的东西:

int (&array2)[5] = (int (&)[5])(*(array1 + 5));

Now array2 will be an array for all intents and purposes, and will be a sub-array of array1, and will even be passable to that famous C++ array_size template function. Though the best way to handle this hackery is to hide it with more hackery!

现在array2将是一个数组,用于所有目的和目的,它将是array1的子数组,甚至可以传递给著名的c++ array_size模板函数。虽然处理这种黑客行为的最好方法是用更多的黑客行为来隐藏它!

#define make_sub_array(type, arr, off, len) (type (&)[len])(*(arr + off));

int (&array2)[5] = make_sub_array(int, array1, 5, 5);

Nice. Terrible by some standards, but the end result a) looks pretty neat, b) does exactly what you want, c) is functionally identical to an actual array, and d) will also have the added bonus (or mis-feature) of being an identical reference to the original, so the two change together.

好了。从某些标准来看,这很糟糕,但是最终结果a)看起来很整洁,b)做了你想做的事情,c)功能上与实际的数组相同,d)也会有额外的好处(或错误的特性),即与原始的引用相同,所以两者一起变化。

UPDATE: If you prefer, a templated version (sort of):

更新:如果你喜欢,模板版本(差不多):

template <typename T, size_t M>
T (&_make_sub_array(T (&orig)[M], size_t o))[]
{
    return (T (&)[])(*(orig + o));
}
#define make_sub_array(type, array, n, o) (type (&)[n])_make_sub_array(array, o)

int (&array2)[5] = make_sub_array(int, array1, 5, 5);

We still have to pass the type. Since one of our arguments must be used as part the cast, we cannot cleanly (IMHO) avoid the macro. We could do this:

我们还得通过这个类型。由于我们的一个参数必须作为角色的一部分使用,我们不能干净地(IMHO)避免宏观。我们可以这样做:

template <typename T, size_t M, size_t N>
T (&make_sub_array(T (&orig)[M], size_t o))[N]
{
    return (T (&)[N])(*(orig + o));
}

int (&array2)[5] = make_sub_array<int, 15, 5>(array1, 5);

But the goal here is to make the calling code as clean as possible, and that call is a bit hairy. The pure-macro version probably has the least overhead and is probably the cleanest to implement in this case.

但是这里的目标是让调用代码尽可能的干净,这个调用有点麻烦。纯宏版本的开销可能最少,在这种情况下可能是最干净的实现。

#3


3  

For a completely different approach you could do something like.

对于完全不同的方法,你可以做一些类似的事情。

vector<int> v0(array1 + 95, array1 + 100);

or

vector<int> v1(array1, array1 + 100);
vector<int> v2(v1.begin() + 95, v1.end());

This would make a real copy of the elements of your vector.

这将是向量元素的真实拷贝。

#4


3  

You can use boost::iterator_range to represent "slices" of arrays/containers:

可以使用boost:::iterator_range表示数组/容器的“片”:

#include <iostream>
#include <boost/range.hpp>

int main()
{
    int array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    // Create a "proxy" of array[5..7]
    // The range implements the concept of a random sequence containter
    boost::iterator_range<int*> subarray(&array[5], &array[7]+1);

    // Output: 3 elements: 5 6 7
    std::cout << subarray.size() << " elements: "
              << subarray[0] << " "
              << subarray[1] << " "
              << subarray[2] << "\n";
}

Note that the iterator range "knows" about the size of the sub-array. It will even do bounds checking for you. You cannot get that functionality from a simple pointer.

注意,迭代器范围“知道”子数组的大小。它甚至可以帮你检查边界。您无法从一个简单的指针中获得该功能。

The usefulness of Boost.Range will become more apparent once you learn about STL containers and iterators.

提高的有效性。一旦您了解了STL容器和迭代器,范围将变得更加明显。

If you're into linear algebra, Boost.uBlas supports ranges and slices for its matrices and vectors.

如果你学的是线性代数,那就用Boost。uBlas支持其矩阵和向量的范围和切片。

#5


1  

In C++ you can use an int pointer as an int array, so getting the array2 to start at item 96 in array1 is easy, but there isn't any way to give array2 a size limit, so you can do this

在c++中,可以使用int指针作为int数组,因此在array1中让array2从第96项开始是很容易的,但是没有办法给array2一个大小限制,所以可以这样做

int array2[] = &array1[96];

int array2[]= &array1[96];

or this

或者这个

int *array2 = &array1[96];

but NOT this

但是不是这个

int array2[5] = &array1[96]; // this doesn't work.

On the other hand, C++ doesn't enforce array size limits anyway, so the only real loss is that you can't use sizeof to get the number of elements in array2.

另一方面,c++并没有强制数组大小的限制,所以唯一真正的损失是您不能使用sizeof来获取array2中的元素数量。

note: &array1[96] is the same thing as array+96

注意:&array1[96]与数组+96相同

edit: correction - int array[] = &array[96] isn't valid, you can only use [] as a synonym for * when declaring a function parameter list.

编辑:校正- int数组[]= &数组[96]是无效的,您只能在声明函数参数列表时使用[]作为*的同义词。

so this is allowed

这是被允许的

extern int foo(int array2[]);
foo (&array1[96]);

#6


0  

int array1[] = {1,2,3,...99,100};
int *array2 = &array1[96];

#7


0  

int arr[] = { 1, 2, 3, 4, 5};
int arr1[2];
copy(arr + 3, arr + 5, arr1);
for(int i = 0; i < 2; i++)
    cout << arr1[i] << endl;

The code is not safe if the boundaries are not handled properly.

如果边界处理不当,代码就不安全。

#8


0  

You said you don't want to copy the array, but get a pointer to the last five elements. You almost had it:

你说过你不想复制数组,但是你可以得到一个指向最后五个元素的指针。你几乎把它:

int array1[] = {1,2,3,...99,100};
int* array2  = &array1[95];