是否可以在不进行额外分配的情况下移动和修改向量?

2024-01-09

考虑以下代码:

let u: Vec<u8> = (64..74).collect();
let v: Vec<u8> = u.iter().map(|i| i + 1).collect();

u没有被移动,因此v不可避免地被重新分配。

但如果我执行以下操作:

let w: Vec<u8> = u.into_iter().map(|i| i + 1).collect();

u被感动了并且w是其转换的名称。这是一些代表我的意思的伪代码:

mark u as "moved"
for i = 0..10:
    u[i] += 1
w = u

(在我看来)不需要新的分配,因为我们将类型映射到自身。对于此代码,情况并非如此:

let t: Vec<u8> = (64..74).collect();
let s: String = t.into_iter().map(|i| i as char).collect();

总结我的问题

有没有新的分配Vec当我们转换一个Vec到一个迭代器中,然后将该迭代器映射到另一个迭代器在相同类型的元素上然后将结果收集到Vec?

如果确实有分配,为什么?

我尝试过了--emit=mir,但我无法找到答案。我每晚都使用 rustc 1.20(如果这很重要的话)。

如果您想玩代码:在线尝试! https://tio.run/##jZDNCsIwEITvPsXaU4oa/4qW@HfyCQQvIhpq1ECaSLKpB/XZa06iWLF73dn5ZtZ6h2V51JBzqUkMtwaEUQLBs7XIpj6dwwzIKKF0nMQ0M0qJDEk8eemKN52nEoUlMc35hdzlXbb6XzcXKzUq3STRjS0eURv8r0XxRrl@UjSa3X9Ut1tJg2mnA8JaYzfL3jAdbBl4J8AcITeFOEDBlRcM9n5fnesa7F/BsOabHFthMDoFGVbmB@4gO3NbqwXWb4E/Wrhg/yjLJw


让我们来看看来源 https://doc.rust-lang.org/stable/src/collections/vec.rs.html#1715-1734的实施情况into_iter() for Vec<T>:

fn into_iter(mut self) -> IntoIter<T> {
    unsafe {
        let begin = self.as_mut_ptr();
        assume(!begin.is_null());
        let end = if mem::size_of::<T>() == 0 {
            arith_offset(begin as *const i8, self.len() as isize) as *const T
        } else {
            begin.offset(self.len() as isize) as *const T
        };
        let cap = self.buf.cap();
        mem::forget(self);
        IntoIter {
            buf: Shared::new(begin),
            cap: cap,
            ptr: begin,
            end: end,
        }
    }
}

创建IntoIter迭代器会产生多次额外的分配,但不会针对向量的元素进行分配;相反,向量的底层内存详细信息被注册。怎么样the code https://doc.rust-lang.org/stable/src/core/iter/iterator.rs.html#479-483 behind map()?

fn map<B, F>(self, f: F) -> Map<Self, F> where
    Self: Sized, F: FnMut(Self::Item) -> B,
{
    Map{iter: self, f: f}
}

这里也没有分配额外的向量。最后一块拼图是collect() https://doc.rust-lang.org/stable/src/core/iter/iterator.rs.html#1255-1257:

fn collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized {
    FromIterator::from_iter(self)
}

这里没有答案;关于什么实施 https://doc.rust-lang.org/stable/src/collections/vec.rs.html#1689-1694 of from_iter() for Vec<T>?

impl<T> FromIterator<T> for Vec<T> {
    #[inline]
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {
        <Self as SpecExtend<T, I::IntoIter>>::from_iter(iter.into_iter())
    }
}

这开始看起来像魔法,但也许相关规范扩展代码 https://doc.rust-lang.org/stable/src/collections/vec.rs.html?search=#1773-1798将揭示我们正在寻找的内容:

impl<T, I> SpecExtend<T, I> for Vec<T>
    where I: Iterator<Item=T>,
{
    default fn from_iter(mut iterator: I) -> Self {
        // Unroll the first iteration, as the vector is going to be
        // expanded on this iteration in every case when the iterable is not
        // empty, but the loop in extend_desugared() is not going to see the
        // vector being full in the few subsequent loop iterations.
        // So we get better branch prediction.
        let mut vector = match iterator.next() {
            None => return Vec::new(),
            Some(element) => {
                let (lower, _) = iterator.size_hint();
                let mut vector = Vec::with_capacity(lower.saturating_add(1));
                unsafe {
                    ptr::write(vector.get_unchecked_mut(0), element);
                    vector.set_len(1);
                }
                vector
            }
        };
        <Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
        vector
    }

    default fn spec_extend(&mut self, iter: I) {
        self.extend_desugared(iter)
    }
}

在这段代码中我们终于可以看到Vec::new and Vec::with_capacity调用的方法为结果向量分配新的空间。

TL;DR: 不,不能移动and修改向量而不需要额外的分配。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在不进行额外分配的情况下移动和修改向量? 的相关文章

随机推荐

  • 哪个 OpenSSL 版本支持 SHA256?

    我编写了一个 PHP 库 它使用openssl verify and openssl sign 使用 SHA256 我认为 SHA256 支持对于 PHP 和 OpenSSL 来说是一种新功能 但我不知道哪个版本开始支持 SHA256 这会
  • 将逗号分隔的字符串转换为单独的行

    我有一个这样的 SQL 表 SomeID OtherID Data abcdef cdef123 18 20 22 abcdef 4554a24 17 19 987654 12324a2 13 19 20 是否有一个查询可以执行类似的查询S
  • C++ 函数模板编译错误“‘containerType’不是模板”

    我正在尝试编写一个函数来 字符串化 参数以用于记录目的 例如 我想写这样的东西 vector
  • DirectX 或 OpenGL [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如果您正在用 C 编写下一个 3D 图形密集型应用程序 例如 3D 建模和动画软件 那么哪一个是更好的选择 如果我们认为 C 是独立于平台的 那
  • 如何配置此 Spring-Boot 应用程序以使用 IAM 角色而不是密钥和机密?

    我有一个与 S3 和 SQS 通信的 Spring Boot 应用程序 它使用 AWS 密钥和机密工作得很好 但我发现我有一个限制 因为我不能使用这些凭证 而必须使用 IAM 实例角色进行身份验证 我没有运气让这个微小的改变发挥作用 我创建
  • 消息队列和共享内存的区别?

    我读了很多关于消息队列和共享内存之间差异的文章 但仍不清楚哪一种有利于获得良好的性能 就像共享内存应该比队列更好 但在同步它的情况下也存在性能问题 共享内存和消息队列都可以用来在进程之间交换信息 区别在于how他们被使用了 共享内存正如您所
  • 如何在 Vim 中的 html 标签之间粘贴内容?

    紧迫p将内容粘贴到当前行下方 dit删除 html 标签内的内容 如何在 html 标签内粘贴内容 Nor here p I want to paste something here p Not here 我通常只是这样做vitp它直观地选
  • VS 2010可以自动检查/更新头文件吗?

    这几乎就是我的问题 VS 2010 可以自动检查和更新 C 代码中的头文件吗 VS 2010可以自动从头文件生成cpp文件 从而节省您从头文件复制函数定义的时间吗 我的意思是 它是否可以认为某些方法没有实现 并从头文件中找到的声明生成一个空
  • 量角器可以慢速运行吗?

    有没有办法缓慢运行使用量角器编写的 Angular E2E 测试 以便我可以观察正在发生的情况 以下是我的解决方案 所以基本上我为当前控制流创建了一个装饰器execute函数 现在在每个排队操作之前额外排队 100 毫秒的延迟 这需要在调用
  • Spring MVC @ResponseBody 返回一个列表

    我们想创建一个 WebService 它返回特定对象的列表 我们想通过 apache http 客户端库从另一个 java 程序调用这个 Web 服务 此时 如果我们从 Firefox 中调用 Web 服务 则会出现 406 错误页面 我们
  • Spring 安全和 JSON 身份验证

    我在 spring spring mvc 中有一个完全使用 JSON 通信的应用程序 现在我需要通过 JSON 使用 spring security 3 使用 LdapAuthenticationProvider 对我的应用程序进行身份验证
  • Doctrine 2.0 中未加载延迟加载属性

    我正在使用 PHP 和 Doctrine 2 0 所有实体都工作正常 除了下面详细介绍的实体关系 或者其他实体在我没有注意到的地方失败 考虑以下实体 Entity class Target ManyToOne targetEntity k
  • 根据浏览器应用不同的 CSS 宽度属性? (IE8、FF)

    我必须将宽度应用于 div 宽度值需要根据浏览器的不同而变化 我无法应用条件 css 那么有什么办法可以做到这一点吗 FF apply width 720px IE8 apply width 690px 可以使用一些技巧将它们组合起来 以便
  • 如何在Android中注册睡眠事件?

    我正在开发 Android 3 0 我需要在我的应用程序中知道设备何时进入睡眠 关闭屏幕 我如何注册此意图 事件 以便在发生这种情况时我能够运行一些操作 BroadcastReceiver 中是否有任何通知此操作的操作 This http
  • 图库中的图像自动旋转 - Android

    在我的 Android 应用程序中 我正在从设备库加载图像 在这方面 我面临着有关图像方向的问题 当我从图库加载高分辨率图像时 它们会自动旋转然后显示在我的视图中 我尝试了有关此问题的各种解决方案 但无法得到正确的解决方案 我提到获取方向
  • 如何正确转义 Makefile 的数据?

    我正在动态生成config mk带有将由 Makefile 使用的 bash 脚本 该文件的构造如下 cat gt config mk lt
  • DMA 与中断驱动的 I/O

    我不太清楚 DMA 和中断 I O 之间的区别 当前正在阅读操作系统概念 第 7 版 具体来说 我不确定在这两种情况下何时会发生中断 以及在这两种情况下 CPU 在什么时候可以自由地执行其他工作 我一直在读但不一定能调和的东西 中断驱动 通
  • 为什么 ICC 在 x86 上的汇编中生成“inc”而不是“add”?

    在摆弄简单的 C 代码时 我注意到一些奇怪的事情 ICC为何产生incl eax在为增量生成的汇编代码中而不是addl 1 eax 不过 GCC 的行为符合预期 使用add 示例代码 O3用于 GCC 和 ICC int A B C D E
  • 如何在 Windows 上使用 GCC 11.1 构建 Qt 5.13.2?

    我已经使用 GCC MinGW w64 在 Windows 上成功构建 Qt 5 很长时间了 当我在 GCC 11 1 上尝试相同的操作时 构建失败并出现奇怪的错误消息 我该怎么做才能让它发挥作用 我自己使用以下方法构建了编译器develo
  • 是否可以在不进行额外分配的情况下移动和修改向量?

    考虑以下代码 let u Vec