如何调整C ++ STL向量的大小(同时调整length
和capacity
的大小,不进行任何初始化?垃圾值是可以接受的!
我知道STL Vector具有resize()
方法,但是此方法涉及初始化,这可能是不必要的。
而且,我在Rust中发现了一个set_len()
函数,它确实可以实现我想要的功能。 C ++ STL是否有一种方法(甚至是hacky)来实现这一目标?
可以在set_len()
中找到Rust中的here文档。
[我知道设置一个大于向量容量的长度是undefined behavior,我必须非常小心(unsafe fn
,很确定),但是我所说的是the_new_length_i_am_setting <= vec.capacity()
是GUARANTEED(我已经正确reserved()
)。
我不太在意那些值会填充到那些多余的空间中(垃圾是可以接受的,因为之后我会手动仔细地覆盖它们。) malloc()
和calloc()
之间的区别是我在说的内容的完美比喻。
我的用例:将来自多个read()
或recv()
调用的字节直接存储到同一向量中,而无需使用额外的数组/缓冲区。 (我已经在Rust的Vec中使用reserve()
然后是set_len()
实现了这一点,但我未能在C ++ STL的set_len()
中找到vector
的等效函数。
为了使内容更容易理解,我基本上是试图在仅接受数组的Linux系统API上使用vector
。在realloc()
-ed数组上调用malloc()
肯定会做同样的事情,但是它容易出错,尤其是在处理索引时。
您可能会说“垃圾值”是可以接受的,但不是。因为当人们说他们的C ++代码中确实包含垃圾值时,实际上并没有,因此实际上它们具有未定义的行为。而且,您不应该轻视未定义的行为。请允许我引用another answer of mine:
void foo();
void bar();
void test(bool cond)
{
int a; // uninitialized
if (cond)
a = 24;
if (a == 24)
foo();
else
bar();
}
用true
调用上述函数的结果是什么? false
怎么办?
[test(true)
将清除呼叫foo()
。
test(false)
如何?如果您回答:“那么,它取决于变量a
中的垃圾值,如果是24
,它将调用foo
,否则它将调用bar
””那么您就完全错了。
[如果调用test(false)
,则程序访问未初始化的变量且具有未定义的行为,这是非法路径,因此编译器可以自由地假定cond
永远不会是false
(因为否则程序将是非法的)。令人惊讶的是,启用了优化的gcc和clang实际上都可以做到这一点,并且函数的generate this assembly:
test(bool):
jmp foo()
这个故事的寓意是UB是UB。不要依赖任何行为。访问未初始化的变量或内存不会导致垃圾值,它会导致UB,并且结果可能非常糟糕,极其令人惊讶且难以调试。
回到您的问题:否,std::vector
中没有办法分配您可以访问的未初始化的内存。即这是UB,您应该100%不这样做:
std::vector<int> v = ...;
v.reserve(v.size() + 100);
v[v.size()] = 11; // Access beyond vector's size,
// Undefined Behavior even if you reserved memory for it
我知道将长度设置为大于向量的容量是未定义的行为
不,不是:
void resize( size_type count );
调整容器的大小以包含计数元素。
如果当前大小小于计数,则附加默认插入元素追加
当然,这样做的缺点是元素将被默认插入。但是,正如我已经说过的,在std:::vector
即使没有std::vector
,理论上实际上也无法做您想做的事情。 C ++中的对象生存期规则存在一个长期存在的问题(即使事实上它实际上被忽略了)。有一篇论文p0593r2试图解决这个问题。但是即使采用了标准中的解决方案,您仍然需要实现自己的容器以允许并执行您想要的操作。