jer*_*c05 4 c++ stl vector rust
如何在不进行任何初始化的情况下调整C++ STL 向量的大小(调整length
两者) ?垃圾值可以接受!capacity
我知道STL Vector有resize()
方法,但是这个方法涉及初始化,这可能是不必要的。
此外,我set_len()
在 Rust 中发现了一个函数,它完全可以满足我的需求。C++ STL 有没有办法(甚至是 hacky)来实现这一点?
Rust 中的文档可以在这里set_len()
找到。
我知道设置大于向量容量的长度是未定义的行为,我必须非常小心(unsafe fn
当然),但我正在谈论那些the_new_length_i_am_setting <= vec.capacity()
有保证的情况(我已经reserved()
正确了)。
我真的不关心这些额外的空格将填充什么值(垃圾是可以接受的),因为之后我会小心地手动覆盖它们。和之间的区别是我正在谈论的内容的完美类比。malloc()
calloc()
我的用例:将来自多个read()
s 或recv()
s 调用的字节直接存储到同一向量中,而不使用额外的数组/缓冲区。(我已经在 Rust 的 Vec 中使用reserve()
and then实现了这一点set_len()
,但我未能set_len()
在 C++ STL 的vector
.
为了让事情更容易理解,我基本上尝试vector
在只接受数组的 Linux 系统 API 上使用。调用-edrealloc()
数组malloc()
肯定会做同样的事情,但它很容易出错,特别是在处理索引时。
你可能会说“垃圾值”是可以接受的,但事实并非如此。因为当人们说他们的 C++ 代码中有垃圾值时,他们实际上没有,他们实际上有未定义的行为。并且您不应该轻视未定义的行为。请允许我引用我的另一个答案:
void foo();
void bar();
void test(bool cond)
{
int a; // uninitialized
if (cond)
a = 24;
if (a == 24)
foo();
else
bar();
}
Run Code Online (Sandbox Code Playgroud)
使用 调用上述函数的结果是什么true
?与 又如何呢false
?
test(true)
会清楚地打电话foo()
。
关于什么test(false)
?如果你回答:“这取决于变量中的垃圾值a
是什么,如果是它24
就会调用foo
,否则它就会调用bar
”那么你就完全错了。
如果您调用test(false)
程序访问未初始化的变量并具有未定义的行为,则它是非法路径,因此编译器可以自由地假设cond
是 never false
(因为否则程序将是非法的)。令人惊讶的是,启用优化的 gcc 和 clang 实际上都执行此操作并为该函数生成此程序集:
test(bool):
jmp foo()
Run Code Online (Sandbox Code Playgroud)
这个故事的寓意是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
Run Code Online (Sandbox Code Playgroud)
我知道设置大于向量容量的长度是未定义的行为
不,这不对:
Run Code Online (Sandbox Code Playgroud)void resize( size_type count );
调整容器大小以包含 count 元素。
如果当前大小小于 count,则附加额外的默认插入元素
当然,这有一个缺点,即元素将被默认插入。但正如我所说,没有办法解决这个问题std:::vector
即使没有 . 做你想做的事情实际上理论上也是不可能的std::vector
。C++ 中的对象生命周期规则存在一个长期存在的问题(尽管事实上它在实践中被忽略)。有一篇论文p0593r2试图解决这个问题。但即使采用了标准的解决方案,您仍然需要实现自己的容器来允许并执行您想要的操作。
归档时间: |
|
查看次数: |
495 次 |
最近记录: |