[C ++ STL Vector等效于Rust中的set_len()

问题描述 投票:0回答:1

TL; DR:

如何调整C ++ STL向量的大小(同时调整lengthcapacity的大小,不进行任何初始化?垃圾值是可以接受的!

问题

我知道STL Vector具有resize()方法,但是此方法涉及初始化,这可能是不必要的。

而且,我在Rust中发现了一个set_len()函数,它确实可以实现我想要的功能。 C ++ STL是否有一种方法(甚至是hacky)来实现这一目标?

可以在set_len()中找到Rust中的here文档。

编辑1

  1. [我知道设置一个大于向量容量的长度是undefined behavior,我必须非常小心(unsafe fn,很确定),但是我所说的是the_new_length_i_am_setting <= vec.capacity()GUARANTEED(我已经正确reserved())。

  2. 我不太在意那些值会填充到那些多余的空间中(垃圾是可以接受的,因为之后我会手动仔细地覆盖它们。) malloc()calloc()之间的区别是我在说的内容的完美比喻。

  3. 我的用例:将来自多个read()recv()调用的字节直接存储到同一向量中,而无需使用额外的数组/缓冲区。 (我已经在Rust的Vec中使用reserve()然后是set_len()实现了这一点,但我未能在C ++ STL的set_len()中找到vector的等效函数。

  4. 为了使内容更容易理解,我基本上是试图在仅接受数组的Linux系统API上使用vector。在realloc() -ed数组上调用malloc()肯定会做同样的事情,但是它容易出错,尤其是在处理索引时。

c++ vector rust stl
1个回答
0
投票

前言(可能很长,但是非常重要)

您可能会说“垃圾值”是可以接受的,但不是。因为当人们说他们的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

我知道将长度设置为大于向量的容量是未定义的行为

不,不是:

std::vector::resize

void resize( size_type count );

调整容器的大小以包含计数元素。

如果当前大小小于计数,则附加默认插入元素追加

当然,这样做的缺点是元素将被默认插入。但是,正如我已经说过的,在std:::vector

中没有解决办法

即使没有std::vector,理论上实际上也无法做您想做的事情。 C ++中的对象生存期规则存在一个长期存在的问题(即使事实上它实际上被忽略了)。有一篇论文p0593r2试图解决这个问题。但是即使采用了标准中的解决方案,您仍然需要实现自己的容器以允许并执行您想要的操作。

© www.soinside.com 2019 - 2024. All rights reserved.