我想使用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) {};
};
编译器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’
这显然意味着不能使用可变大小的数组作为类成员。如果是这样,这将否定boost :: array相对于向量或标准数组的所有优点。
你能告诉我我做错了吗?
答案 0 :(得分:19)
Boost的数组是基于第二个模板参数的固定大小,而boost::array<int,4>
是来自boost::array<int,2>
的不同类型。您不能拥有同一类的实例(在您的示例中为MyClass),这些实例的成员具有不同的类型。
但是,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;
}
也就是说,boost :: array仍然有用(在这个示例代码中它甚至很有用),只是没有你想要使用它的确切方式。
答案 1 :(得分:12)
你遗漏了一些基本要点。你可以:
char arr[10];
char* arr = new arr[10];
第一个的大小在编译期间是已知的(因为大小是常量),因此你可以为它预先分配一个内存空间,另一个不是,因此你需要分配在运行期间为它记忆。
STL / TR1 / Boost为两种类型的数组提供包装器。这些不仅包括对手的包装,也包括安全性(在某些情况下进行范围检查)和电源(迭代器)。对于这两种情况,我们都有一个单独的包装器:
boost::array<char,10> arr;
std::vector<char> arr;
后者具有自我调整大小的优点,除了可动态分配外,还允许调整大小。另一方面,boost::array
模仿type arr[const]
构造。
因此,您需要决定是要让类具有静态分配的内存还是动态分配内存。前者只有在类存储是固定大小或几个固定大小之一时才有意义。后者在所有其他情况下都有意义。
静态分配将使用模板
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);
但是会为每个类的大小创建单独的代码,并且它们不会互操作(尽管可以绕过它)。
动态分配将使用向量
class MyClass {
private:
std::vector< int > array;
public:
MyClass(const std::vector< int >& array) : array(array) {};
};
不要害怕向量,将它们视为动态分配的数组 - 向量的大小调整是一个额外的好处,几乎不影响性能。
答案 2 :(得分:6)
我建议您使用boost::scoped_array吗?另一方面,您可能不希望每次都复制整个数组。那么boost::shared_array将是更好的选择。
答案 3 :(得分:3)
不,boost :: array(它在TR1中作为std :: tr1 :: array)是一个静态大小的缓冲区。该类的要点是避免动态内存分配 - 你可以将boost :: array完全放在堆栈上。
您可以使您的示例类获取模板int并将其传递给boost :: array成员
template<int Size>
class MyClass
{
private:
boost::array<int, Size> m_array;
public:
// ....
};
但这只是穿衣,它仍然是静态分配。
答案 4 :(得分:1)
你错了:
template<unsigned long N> MyClass(boost::array<int, N> array) : array(array) {};
应该有效。顺便说一下,这仍然会在编译时生成数组,所以这不是一个好的解决方案。还会发生其他错误。
这里你想要的是一个向量,具有保留的大小和一些断言,使容量保持固定的大小。
答案 5 :(得分:1)
虽然您已经接受了答案,但请注意,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; }
};
编辑:正如Nikolai N Fetissov所说,boost :: scoped_array可能是一个不错的选择。它在阵列周围提供了一个薄的RAII包装器。这是一个用法示例(希望它是正确的,随意编辑):
class MyClass {
private:
boost::scoped_array<int> array;
public:
MyClass( int* array )
: array(array) {}
};
答案 6 :(得分:0)
如果您不需要动态调整大小,则不需要std :: vector
只需要函数accept * int
MyFunction (int* array,int size); // function prototype
并将boost :: array的.data()指针传递给数据......
boost::array<int,4> testArray;
boost::array<int,5> testArray2;
// Calling the function:
MyFunction(testArray.data(),4);
MyFunction(testArray2.data(),5);
关键是.data()人!!!如果你想要使用boost数组替换常规数组,这可能就是这种方式(不必使用模板和所有这些)