C++ STL Vector 相当于 Rust 中的 set_len()

标签 c++ vector rust stl

TL;博士:

如何调整(调整 lengthcapacity 的)C++ STL vector 没有任何初始化 ?垃圾值是可以接受的!

问题

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

此外,我发现了一个 set_len() Rust 中的函数正是我想要的。 C++ STL有没有办法(甚至是hacky)来实现这一点?
set_len()可以找到 Rust 中的文档 here .

编辑 1

  • 我知道设置大于 vector 容量的长度是未定义的行为 ,而且我必须非常小心(unsafe fn,果然如此),但我说的是那些 the_new_length_i_am_setting <= vec.capacity()保证 (我已经 reserved() 正确)。
  • 我真的不在乎那些额外的空格会填充什么值(垃圾是可以接受的),因为之后我会仔细手动覆盖它们。 malloc() 之间的区别和 calloc()是我所说的一个完美的类比。
  • 我的用例:存储来自多个 read() 的字节s 或 recv() s 直接调用同一个 vector ,而不使用额外的数组/缓冲区。 (我在 Rust 的 Vec 中使用 reserve() 然后 set_len() 实现了这一点,但我未能在 C++ STL 的 set_len() 中找到 vector 的等效函数。
  • 为了让事情更容易理解,我基本上是尝试使用 vector在仅接受数组的 Linux 系统 API 上。调用realloc()malloc() -ed 数组肯定会做同样的事情,但它很容易出错,尤其是在处理索引时。
  • 最佳答案

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

    您可能会说“垃圾值”是可以接受的,但事实并非如此。因为当人们说他们的 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 没有办法分配您可以访问的未初始化内存。 IE。这是 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
    

    I am aware that setting a length that is larger than the vector's capacity is undefined behavior



    不,这不对:

    std::vector::resize

    void resize( size_type count );
    

    Resizes the container to contain count elements.

    If the current size is less than count, additional default-inserted elements are appended



    当然,这样做的缺点是元素将被默认插入。但正如我所说,在 std:::vector 中没有办法解决这个问题。

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

    关于C++ STL Vector 相当于 Rust 中的 set_len(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61434924/

    相关文章:

    c++ - 相对于使用堆,使用带有 insert() 的 vector 作为优先级队列的开销是多少? (c++)

    c++ - vector push_back 对元素地址的影响

    c++ - 使标题看起来像是在不同的文件夹中

    c++ - Windows 进程和 WSL Linux 进程之间的共享内存

    c++ - 检查 "Whether for a given directed graph there is only one way to sort the graph using topological sort or not"的算法优化

    c++ - 如何实现指向其他多类型 vector 的 C++ vector ?

    rust - 避免 "use of possibly uninitialized variable"结构中的 "match"在 Rust 中 undefined variable 时无法访问

    reference - 用于处理对缓冲区的引用的惯用 Rust 方法

    asynchronous - 如何修复 reqwest json 解码错误?

    c++ - 返回指向局部变量的指针总是未定义的行为