C++ 如何使用未知大小的 boost::array 作为对象变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2031940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use boost::array with unknown size as object variable
提问by Michael Kowhan
I'd like to use boost::array as a class member, but I do not know the size at compile time. I thought of something like this, but it doesn't work:
我想使用 boost::array 作为类成员,但我不知道编译时的大小。我想到了这样的事情,但它不起作用:
int main() {
boost::array<int, 4> array = {{1,2,3,4}};
MyClass obj(array);
}
class MyClass {
private:
boost::array<int, std::size_t> array;
public:
template<std::size_t N> MyClass(boost::array<int, N> array)
: array(array) {};
};
The compiler, gcc, says:
编译器 gcc 说:
error: type/value mismatch at argument 2 in template parameter list for
‘template<class _Tp, long unsigned int _Nm> struct boost::array'
error: expected a constant of type ‘long unsigned int', got ‘size_t'
Which obviously means that one cannot use variable-sized arrays as class members. If so, this would negate all the advantages of boost::array over vectors or standard arrays.
这显然意味着不能使用可变大小的数组作为类成员。如果是这样,这将否定 boost::array 相对于向量或标准数组的所有优势。
Can you show me what I did wrong?
你能告诉我我做错了什么吗?
回答by
Boost's array is fixed-size based on the second template parameter, and boost::array<int,4>
is a different typefrom boost::array<int,2>
. You cannot have instances of the same class (MyClass in your example) which have different types for their members.
升压的阵列是基于所述第二模板参数固定大小的,并且boost::array<int,4>
是一个不同类型从boost::array<int,2>
。您不能拥有相同类(在您的示例中为 MyClass)的实例,它们的成员具有不同的类型。
However, std::vectors can have different sizes without being different types:
但是, std::vectors 可以有不同的大小而不是不同的类型:
struct MyClass {
template<std::size_t N>
explicit
MyClass(boost::array<int, N> const& array)
: data(array.begin(), array.end())
{}
private:
std::vector<int> data;
};
int main() {
boost::array<int, 4> a = {{1,2,3,4}};
MyClass obj(a);
boost::array<int, 2> a2 = {{42,3}};
MyClass obj2(a2);
// notice obj.data.size() != obj2.data.size()
return 0;
}
That said, boost::array is still useful (it's even useful in this example code), just not in the exact way you want to use it.
也就是说, boost::array 仍然很有用(它在本示例代码中甚至很有用),只是不是以您想要的确切方式使用它。
回答by Kornel Kisielewicz
You're missing some basic points. You can have:
你缺少一些基本点。你可以有:
- A staticallyallocated array -
char arr[10];
- A dynamicallyallocated array -
char* arr = new arr[10];
- 一个静态分配的数组 -
char arr[10];
- 甲动态分配的数组-
char* arr = new arr[10];
The first one's size is known during compile time (because the size is a constant), hence you can preallocate a memory space for it, the other one isn't, hence you need to allocate memory for it during run-time.
第一个的大小在编译时是已知的(因为大小是一个常量),因此您可以为它预先分配内存空间,另一个不是,因此您需要在运行时为其分配内存。
STL/TR1/Boost provides wrappersfor both types of arrays. Those are not only wrappers for convieniece, but also for safety (range checking in some situations) and power (iterators). For both cases we have a separate wrapper:
STL/TR1/Boost为这两种类型的数组提供了包装器。这些不仅是方便的包装器,也是安全(某些情况下的范围检查)和电源(迭代器)的包装器。对于这两种情况,我们都有一个单独的包装器:
- Statically allocated array wrapper
boost::array<char,10> arr;
- Dynamically allocated array wrapper
std::vector<char> arr;
- 静态分配的数组包装器
boost::array<char,10> arr;
- 动态分配的数组包装器
std::vector<char> arr;
The latter has the benefit of being self resizing, and allowing resizing, in addition to being dynamically allocatable. boost::array
on the other hand, mimics a type arr[const]
construct.
后者除了可以动态分配之外,还具有自我调整大小和允许调整大小的好处。boost::array
另一方面,模仿一个type arr[const]
构造。
Hence, you need to decide whether you want the class to have statically allocated memory, or dynamically. The former, only makes sense if the classes storage is either fixed size, or one of a few fixed sizes. The latter makes sense in all other cases.
因此,您需要决定是希望类具有静态分配的内存还是动态分配的内存。前者只有在类存储是固定大小或几个固定大小之一时才有意义。后者在所有其他情况下都有意义。
Statically allocated would use templates
静态分配将使用模板
template < size_t N >
class MyClass {
private:
boost::array< int, N > array;
public:
MyClass(boost::array< int, N > array) : array(array) {};
};
// ...
boost::array<int, 4> array = {{1,2,3,4}};
MyClass<4> obj(array);
But would create separate code for every size of the class, and they would not be inter-operable (this can be circumvented though).
但是会为类的每个大小创建单独的代码,并且它们不能互操作(尽管可以规避)。
Dynamically allocated would use vectors
动态分配将使用向量
class MyClass {
private:
std::vector< int > array;
public:
MyClass(const std::vector< int >& array) : array(array) {};
};
Don't be afraid of vectors, treat them as dynamically allocated arrays -- the resizingness of vectors is an added benefit that doesn't affect performance almost at all.
不要害怕向量,将它们视为动态分配的数组——向量的大小调整是一个额外的好处,几乎完全不会影响性能。
回答by Nikolai Fetissov
May I suggest using boost::scoped_arrayinstead? On the other hand, you might not want to actually copythe whole array every time. Then boost::shared_arraywould be a better choice.
我可以建议改用boost::scoped_array吗?另一方面,您可能不想每次都实际复制整个数组。那么boost::shared_array将是更好的选择。
回答by Terry Mahaffey
No, boost::array (it's in TR1 as std::tr1::array) is a statically sized buffer. The point of the class is to avoid a dynamic memory allocation - you can put a boost::array entirely on the stack.
不,boost::array(它在 TR1 中作为 std::tr1::array)是一个静态大小的缓冲区。该类的重点是避免动态内存分配 - 您可以将 boost::array 完全放在堆栈上。
You can make your example class take a template int and pass that to the boost::array member,
您可以让示例类采用模板 int 并将其传递给 boost::array 成员,
template<int Size>
class MyClass
{
private:
boost::array<int, Size> m_array;
public:
// ....
};
But that is just dressing, it's still a static allocation.
但这只是穿衣,它仍然是静态分配。
回答by Frunsi
Though you already accepted an answer, please note that std::vector may notbe the right choice for your task. If you want to create the array once - a fixed size array- and you do not want to resize it later on, then a good old plain arraymay be the right choice for you! Ignore boost::array, ignore std::vector, its intents are very different, keep it simple. KISS, YAGNI and so on...
尽管您已经接受了答案,但请注意 std::vector 可能不是您任务的正确选择。如果您想一次创建数组 -一个固定大小的数组- 并且您不想稍后调整它的大小,那么一个好的旧普通数组可能是您的正确选择!忽略 boost::array,忽略 std::vector,它的意图是非常不同的,保持简单。KISS、YAGNI等等……
int main() {
int* array = new int[4];
for( int i=0; i<4; ++i ) array[i] = i+1;
MyClass obj(array);
}
class MyClass {
private:
int* array;
public:
MyClass( int* array )
: array(array) {}
~MyClass() { delete[] array; }
};
EDIT:As Nikolai N Fetissov already stated, boost::scoped_array might be a good choice. It provides a thin RAII wrapper around the array. Here is a usage example (hope it is correct, feel free to edit otherwise):
编辑:正如 Nikolai N Fetissov 已经说过的, boost::scoped_array 可能是一个不错的选择。它在阵列周围提供了一个薄的 RAII 包装器。这是一个用法示例(希望它是正确的,否则请随意编辑):
class MyClass {
private:
boost::scoped_array<int> array;
public:
MyClass( int* array )
: array(array) {}
};
回答by Klaim
You're wrong about the error :
你错了这个错误:
template<unsigned long N> MyClass(boost::array<int, N> array) : array(array) {};
Should work. By the way this will still generate the array at compile time so it's not a good solution. And other errors will occur.
应该管用。顺便说一下,这仍然会在编译时生成数组,所以这不是一个好的解决方案。并且会出现其他错误。
Here what you want is a vector, with a reserved size and some assertions that keep the capacity on a fixed size.
这里你想要的是一个向量,它有一个保留的大小和一些将容量保持在固定大小的断言。
回答by Mike Gao
If you don't need dynamic resizing, you don't need std::vector
如果不需要动态调整大小,则不需要 std::vector
just have the function accept *int
只是让函数接受 *int
MyFunction (int* array,int size); // function prototype
and pass it the boost::array 's .data() pointer to the data...
并将 boost::array 的 .data() 指针传递给数据...
boost::array<int,4> testArray;
boost::array<int,5> testArray2;
// Calling the function:
MyFunction(testArray.data(),4);
MyFunction(testArray2.data(),5);
the key is .data() people!!! If you want boost arrays to replace regular arrays, this is perhaps the way (without having to use templates and all that)
关键是 .data() 人!!!如果您希望 boost 数组替换常规数组,这可能是方法(无需使用模板等)