我需要C++向量的最大大小(我给出的值)
I need the max size of my vector (the value I gave) C++
我有以下代码:
固定大小的矢量:
template <typename T, size_t siz>
struct fixVec : public std::vector<T> {
void push_back(const T& d) {
if (std::vector<T>::size() >= siz) throw std::bad_alloc();
std::vector<T>::push_back(d);
}
};
我像这样使用"fixVec":
ClonableHeteroStore<ClonableTestClass, fixVec<ClonableTestClass*, 1>, MyException> t1;
它创建一个大小为 1 的向量。(1)
EXPECT_NO_THROW(t1.add(new ClonableTestClass));
它添加了 1 个元素,它很好,没有错误。(二)
EXPECT_THROW(t1.add(new ClonableTestClass), MyException);
在这里它应该抛出异常。(三)
我的问题是:我如何检查何时到达 MY 向量的"max_size()"。不是我的电脑可以处理的矢量的最大大小。 或者我怎样才能找回我在代码(1)中给出的值(!
ClonableHeteroStore<ClonableTestClass, fixVec<ClonableTestClass*, !!!1!!! >, MyException> t1;
我有一个名为 ClonableHeteroStore 的类,其中有以下代码:
template <typename T1, class S, typename PRED = int>
class ClonableHeteroStore
{
private:
S flakker;
size_t currently;
size_t maxi;
public:
ClonableHeteroStore() : { currently = 0; maxi = 0; }
void add(T1 *rhs)
{
if (currently < ???????? )
{
flakker.push_back(rhs);
currently++;
}
else
{
delete rhs;
throw PRED();
}
}
它应该做什么: 如果我们没有达到我们在代码(1)中给出的向量的最大大小,它应该向向量添加一个新元素。如果我们达到了代码(1)中给出的限制,它应该会删除异常。
所以第 (2)行不会有任何问题,因为向量的大小是 1,这是我们放入其中的第一个元素。"如果"部分应该运行。
第(3)行将引发异常,因为它尝试放置第二个元素,但向量大小为1。"其他"部分应该运行。
唯一可以更改的代码是 ClonableHeteroStore 类。 不知何故,我应该找出,我的向量有多大。我读了很多向量动态分配它的大小等,但在这种情况下,如果我跳过限制 (1),它必须抛出异常。
感谢您的任何帮助!
从类型中提取模板参数的两种常见解决方案是使用部分显式专用化的类型特征或使用函数模板从函数参数推断模板参数的类型特征。基于函数的方法包括编写一个需要fixVec<T, I>
的函数,并让编译器推导出I
:
// The compiler will deduce T and I from the argument
template<class T, size_t I>
size_t get_vec_size(const fixVec<T, I> &) {
return I;
}
void foo()
{
fixVec<char, 10> my_vec;
const auto my_vec_max_size = get_vec_size(my_vec);
}
要使用部分显式专用化,您可以编写一个新模板并将其专用化为您需要其模板参数的类型,并再次让编译器为您推断这些参数:
template<class T>
struct vec_size {};
template<class T, size_t I>
struct vec_size<fixVec<T, I>> : std::integral_constant<size_t, I> {};
void foo()
{
fixVec<char, 10> my_vec;
const auto my_vec_max_size = vec_size<decltype(my_vec)>::value;
}
有趣的问题!
例如,您可以使用模板模板参数:
template<template<typename, size_t> typename X, typename T, size_t N>
constexpr size_t get_size(const X<T, N>&) {
return N;
}
int main() {
std::cout << get_size(fixVec<int, 5>{}) << std::endl;
}
这不仅适用于fixVec
,也适用于任何具有类型和size_t作为模板参数的模板类型!
因此,例如以下内容也是有效的:
get_size(std::array<int, 5>{});
固定大小的向量:
为什么对"固定"数组使用std::vector
而不是std:array
?
它创建一个大小为 1 的向量。(1)
不,它没有。 它创建一个vector
,其size()
和capacity()
最初为 0,而不是 1。 您的siz
值被用作人工最大容量,您仍然允许向量动态增长,直到达到最大值。
EXPECT_THROW(t1.add(new ClonableTestClass), MyException);
在这里它应该抛出异常。(三)
没错,更糟糕的是,它因此泄漏了ClonableTestClass
对象。 您应该改用std::unique_ptr<ClonableTestClass>
,以便始终保持对象的所有权并正确释放它,即使引发异常也是如此。
如何检查何时到达 MY 向量的"max_size()"。
你已经是了。 这正是size() >= siz
正在做的事情。
或者我怎样才能找回我在代码 (1) 中给出的值(!
ClonableHeteroStore<ClonableTestClass, fixVec<ClonableTestClass*, !!!1!!! >, MyException> t1;
它仅在siz
模板参数中可用。 如果你想让 OUTER 代码知道siz
的值,那么你需要公开对它的公共访问,例如:
template <typename T, size_t siz>
struct fixVec : public std::vector<T>
{
const size_t max_elements_allowed;
fixVec() : max_elements_allowed(siz) {}
...
};
或者,如果您使用的是 C++11 或更高版本:
template <typename T, size_t siz>
struct fixVec : public std::vector<T>
{
const size_t max_elements_allowed = siz;
...
};
然后你可以这样做:
void add(T1 *rhs)
{
if (currently < flakker.max_elements_allowed)
{
flakker.push_back(rhs);
currently++;
}
else
{
delete rhs;
throw PRED();
}
}
仅供参考,您真的不需要currently
,您可以改用flakker.size()
:
void add(T1 *rhs)
{
if (flakker.size() < flakker.max_elements_allowed)
{
flakker.push_back(rhs);
}
else
{
delete rhs;
throw PRED();
}
}
也就是说,std::vector
有一个capacity()
的方法,这正是您真正想要的:
void add(T1 *rhs)
{
if (flakker.size() < flakker.capacity())
{
flakker.push_back(rhs);
}
else
{
delete rhs;
throw PRED();
}
}
你只需要预先分配vector
的内部数组:
template <typename T, size_t siz>
struct fixVec : public std::vector<T>
{
fixVec() { std::vector<T>::reserve(siz); } // <-- add this!
...
};
我有一个名为 ClonableHeteroStore 的类,其中有以下代码:
...
它应该做什么:如果我们没有达到我们在代码 (1) 中给出的向量的最大大小,它应该向向量添加一个新元素。如果我们达到了代码 (1) 中给出的限制,它应该删除一个异常。
由于您的fixVec
已经在处理这个问题,因此您应该无条件地添加元素,并在需要时push_back()
抛出:
void add(T1 *rhs)
{
try
{
flakker.push_back(rhs);
}
catch (...)
{
delete rhs;
throw PRED();
}
}
更好的设计是让调用方维护要添加的对象的所有权,除非add()
成功,否则不要释放该所有权。 这样,如果引发异常,调用方可以正确释放对象,而不会泄漏它。 这不应该是add()
的责任来处理:
void add(T1 *rhs)
{
try
{
flakker.push_back(rhs);
}
catch (...)
{
throw PRED();
}
}
...
ClonableTestClass *obj = new ClonableTestClass;
try
{
t1.add(obj);
}
catch (...)
{
delete obj;
throw;
}
或者,如果您使用的是 C++11 或更高版本:
std::unique_ptr<ClonableTestClass> obj(new ClonableTestClass);
t1.add(obj.get());
obj.release();
或:
void add(std::unique_ptr<T1> rhs)
{
try
{
flakker.push_back(rhs.get());
rhs.release();
}
catch (...)
{
throw PRED();
}
}
...
t1.add(std::unique_ptr<ClonableTestClass>(new ClonableTestClass));
唯一可以更改的代码是 ClonableHeteroStore 类。 不知何故,我应该找出,我的向量有多大。
如果你不能改变fixVec
来公开它的siz
值,你必须找出它的siz
,那么你就必须诉诸一些模板技巧,例如:
template<typename T, size_t siz>
size_t get_capacity(const fixVec<T, siz> &) { return siz; }
...
void add(T1 *rhs)
{
if (flakker.size() < get_capacity(flakker))
flakker.push_back(rhs);
else
throw PRED();
}
但是,这正是 STL 容器公开标准size()
和capacity()
方法的原因,因此您不必诉诸这样的技巧。
另一方面,ClonableHeteroStore
实际上并不需要知道siz
值。 它应该无条件地执行push_back()
,并在需要时让它扔掉。
我读了很多向量动态分配它的大小等,但在这种情况下,如果我跳过限制 (1),它必须抛出异常。
你真的应该使用std::array
而不是std::vector
。
如果必须使用std::vector
,则应考虑编写自定义Allocator
供vector
使用,而不是使用默认Allocator
。 如果要求自定义Allocator
为太多元素分配内存,则可以抛出该。 然后,您可以让std::vector
正常运行,而根本不覆盖其push_back()
。
- 写入向量<向量<bool>>
- 函数向量_指针有不同的原型,我可以构建一个吗
- std::向量与传递值的动态数组
- 将值指定给向量(2D)的向量中的某个位置
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 如何使用向量的template_back函数
- 尝试通过多个向量访问变量时,向量下标超出范围
- 如何通过派生类函数更改基类中的向量
- C++从另一个类访问公共静态向量的正确方法是什么
- 如何将ampl中的集合表示为c++中的向量
- 变量没有改变?通过向量的函数调用
- 迭代时从向量和内存中删除对象
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 计算排序向量的向量中唯一值的计数
- 矩阵向量乘法(cublasDgemv)返回零
- 一对向量构造函数:初始值设定项列表与显式构造
- 将结构向量排序为子组
- 在C++中调整向量中的索引
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么