C++ std::ranges::transform用法 _ 容器元素批量映射变换【详解】

雨枫大大_5257

雨枫大大_5257

2026-04-13

927人浏览

原创

std::ranges::transform 编译失败的根本原因是输入与输出范围存在潜在重叠或不满足 weakly_incrementable/indirectly_writable 概念约束;它要求输入输出不能重叠、目标空间需预先分配或用 back_inserter、二元变换需两范围等长,且返回 void。

c++ std::ranges::transform用法 _ 容器元素批量映射变换【详解】

std::ranges::transform 是 C++20 引入的范围算法,它比传统 std::transform 更安全、更简洁——但仍不自动分配目标空间,且对迭代器重叠有严格限制。

为什么 std::ranges::transform 有时编译不过

根本原因:C++20 范围库要求输入和输出范围必须满足 weakly_incrementable 和 indirectly_writable 约束,且不允许部分重叠(哪怕只是起始位置相同)。

  • 错误写法:std::ranges::transform(v, v.begin(), [](int x) { return x * 2; }); —— 编译失败,提示 no matching function for call to 'transform',因为输入视图 v 和输出迭代器 v.begin() 被视为潜在重叠
  • 正确写法(原地):std::ranges::transform(v, v.begin(), [](int x) { return x * 2; }); 实际上仍可能失败;应改用 std::ranges::for_each(v, [](int& x) { x *= 2; }); 或显式传入 std::ranges::subrange(v.begin(), v.end()) 配合 v.begin()
  • 若目标是另一容器,必须确保其已预留空间或使用 std::back_inserter,否则运行时越界(和老版一样,不报错但行为未定义)

std::ranges::transform 一元变换怎么配参数

签名是 transform(Range&& r, O iter, F f),其中 R 是可范围化类型(vector、array、string 等),O 是输出迭代器,F 是一元可调用对象。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 安全写法(目标容器预分配):std::vector<int> dst(src.size()); std::ranges::transform(src, dst.begin(), [](int x) { return x + 1; });</int>
  • 动态追加写法:std::vector<int> dst; std::ranges::transform(src, std::back_inserter(dst), [](int x) { return x + 1; });</int>
  • 不能直接写 std::ranges::transform(src, dst, ...) —— dst 是容器,不是迭代器;必须用 dst.begin() 或 std::back_inserter(dst)
  • 对 std::vector<bool></bool> 仍不友好:*it 返回代理引用,lambda 参数若写成 bool x 会强制拷贝;建议用 const bool& x 或换用传统循环

std::ranges::transform 二元变换要注意什么

双输入版本签名是 transform(R1&& r1, R2&& r2, O iter, F f),用于逐位置合并两个范围。它比老版 std::transform 更强调“范围等长”语义。

  • 两个输入范围长度必须完全一致,否则编译期或运行期行为未定义(取决于实现);不会像老版那样只处理到较短者末尾
  • 错误示范:std::ranges::transform(a, b, dst.begin(), std::plus{});,其中 a.size() != b.size() → 可能崩溃或静默截断
  • 安全做法:先断言 assert(a.size() == b.size());,再调用;或用 std::views::zip + std::ranges::for_each 显式控制
  • 输出迭代器不能来自任一输入范围(哪怕只是地址不同);例如 std::ranges::transform(a, b, a.begin(), ...) 会被拒绝,因 a 同时作为输入和输出源

std::ranges::transform 和 std::transform 的关键区别在哪

表面是语法糖,实质是约束模型升级:前者基于概念(range, indirectly_readable),后者基于迭代器对;但二者在内存管理责任上完全一致——都不扩容、不检查越界、不处理重叠。

  • std::transform 接受四个迭代器(first1, last1, first2, d_first),易错配;std::ranges::transform 接收范围+迭代器,更直观但隐藏了 last 边界,依赖范围自身大小
  • 当需要“过滤+变换”时,std::ranges::transform 依然无法替代 std::views::filter | std::views::transform;单独用它只会把被“过滤掉”的位置填成默认值(比如 0)
  • 性能上无本质差异;但 std::ranges::transform 在启用 -D_GLIBCXX_CONCEPTS 时可能触发额外编译期检查,略微拖慢构建
  • 最易忽略的一点:std::ranges::transform 返回 void,而 std::transform 返回输出迭代器末位置——如果你依赖那个返回值做链式操作,得回退到老接口

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6199

3

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

2158

7

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

2158

7

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6199

3

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.08.29

3005

6

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

3868

10

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.29

2705

10

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.23

636

5

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.27

351

13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习