首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【笔记】《C++Primer》—— 第16章:模板与泛型编程

函数指针调用存在歧义,我们可以显式指定指针类型来消歧义 具体来说编译器如何从模板函数调用中推断具体实参类型呢,要分为几种情况 函数参数是普通左值,正常推断,很多参数无法传递进去 函数参数是左值引用如...T&,代表我们只能传递给他一个左值,此时如果是T则得到类型T,如果是const T则得到const T 函数参数是const引用时,我们直到我们可以传递给他任何实参,此时const...函数参数本身,所以推断出类型将不再有const部分,基本上是将类型本身取出来了 函数参数是右值引用时,我们可以传递右值,此时推断过程类似左值引用推断,也会随传递参数有无const而受到改变...上面复杂规则总结起来就是“更特例化”,在没有歧义情况下,永远会调用发生了最少改变,最精确匹配,最不需要调用自定义类型转换(内置类型转换优先级更高),最不需要调用模板那个重载 编译器缺少一个合适重载函数...(q); } 对于不同函数调用编译器会实例出不同版本模板函数,这里要注意一个模板只能有一个参数包存在,且参数包一般被写在最右方防止二义性,如果出现了二义性,我们可以显式在调用时尖括号里标明各个模板参数类型

1.5K30

property属性相关小记

,再将输入对象索引值计数增加1 weak:增加引用计数,持有对象,所以不能决定对象释放,对比assign好处是,对象消失时指针自动归为nil assign:适用于基础数据类型,增加引用计数,...因此,对于源头是可变变量,不可变变量仅仅是指针引用源头改变,若使用strong声明,不可变变量会跟随变化;而copy声明,是深拷贝,不会跟随改变。...(runtime如何实现weak变量自动置nil) 不需要。在释放调用clearDeallocating函数。...weak引用指向对象释放如何去处理weak指针呢?...若成员已经存在,则不再生成 在protocol和category中如何使用@property 在两者中,都会生成setter和getter方法声明。

1.1K20
您找到你想要的搜索结果了吗?
是的
没有找到

Rust所有权

在没有 GC 语言中,需要手动识别出不再使用内存并调用代码显式释放,跟请求内存时候一样。 Rust 采取了一个不同策略:内存在拥有它变量离开作用域后就被自动释放。 3....对于在堆上变量,比如 String,将一个 String 变量赋值给另一个 String 变量,拷贝只是存储在栈上内容: let s1 = String::from("hello"); let...image.png 【注】「将值传递给函数」以及「将值从函数返回」在语义上与给变量赋值相似。 3.2 克隆 对于栈上变量,将一个变量赋值给另一个变量即为克隆。...引用 如果我们想将一个 String 变量传给调用函数,并在调用函数后仍然能够使用该 String: 一种方式是将该 String 作为函数返回值一部分,但这过于繁琐。...("{}", r3); 编译器会确保指向 String 引用持续有效。 【注】在任意给定时间,要么只能有一个可变引用,要么只能有多个不可变引用;而且在作用域内引用必须总是有效

62720

Rust学习:如何解读函数签名?

这是因为fn walk_dog(dog: Dog){}接受Dog值,我们没有告诉编译器它们是可复制!传递参数给函数,可复制值会被隐式复制。...当你遛狗,通常狗最终会和你一起回到家里,对吧? Rust使用&来表示借用。借用某个值告诉编译器函数调用完后,值所有权将返回给调用者。...(rover.walked, true); } 正如你所看到函数签名告诉程序员一个值是否可变以及该值是否已被使用或引用。 返回值 让我们重新审视我们如何获得Rover,这是我们探索如何返回类型!...书写函数签名,你想使用像Iterator这样语句来表明一个Dog迭代器。 传递函数 有时需要将函数递给其他函数。在Rust中,接受函数作为参数是相当简单。...所有闭包实现FnOnce:如果闭包仅实现FnOnce,则只能调用一次。 转移捕获变量所有权闭包实现FnMut,允许多次调用它们。

2K40

透过 Rust 探索系统本原:内存管理

我们先用一幅图看 move 是如何处理: ? 这段简单代码里,我们生成了一个 User 对象,然后将其传递给 insert() 函数。...由于两个独立线程生命周期完全无法比较,所以存在 user 结束生命期被释放,而其另一个线程中引用还继续存在情形。...还需要什么信息? 编译编译器能够依赖主要信息来源是类型。对于一个函数调用,其期待输入(输出)类型,和实际传入(传出)类型匹配,那么编译器就可以稳稳地抛出编译错误。...在上图,&user 因为在另一个线程中使用,存在和 user 生命期匹配问题,那么,如果我们明确界定在创建线程,允许传递什么生命周期数据,不就可以把生命期匹配问题杜绝了么?...虽然 Rust 编译器做了很多工作,使得 80% 常用场景下,你不需要标注生命周期,编译器会自动推导;但还是有一些场合,你需要手工添加生命周期,告诉编译器你对调用期待。

1.1K20

计算机小白成长历程——函数(3)

嵌套调用 理解:对嵌套调用理解就是在函数体内调用其它函数。...a+b,第二次打印中printf参数是局部变量c,第三次打印中printf参数是自定义函数sum,接下来我们看看打印值会不会有什么不同: 从打印结果我们可以总结一个函数参数可以是式子、变量以及函数...,一个函数作为另一个函数参数是,就可以说是另一个函数通过链式访问了这个函数。...六、函数声明与定义 函数声明 定义:告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在函数声明决定不了。 特点:1.函数声明一般出现在函数使用之前。要满足先声明后使用。...我们要引用刚刚定义函数,只需要引用我们创建具有函数声明头文件,此时使用双引号来进行引用引用完头文件,我们就能正常使用自己定义函数了。

9620

Java8中Lambda表达式 - 崔笑颜博客

下面分别说下语法中三个组成部分 参数: 1 ( Dog dog ) 参数类型可省略(编译器可以自动推导),比如Comparator comparatorTest = (a, b...@FunctionalInterface可以省略,但是建议加上,就是为了告诉编译器,这是一个函数式接口,此时如果该接口有多个抽象方法,那么编译器就会报错 反例:比如A extends B,A和B各有一个抽象方法...什么是构造引用 上面介绍了方法引用,就是直接引用某个方法 这里构造引用同理可得,就是引用某个类构造方法 构造引用表达式为:Class::new,仅此一种 如果你有多个构造函数,那编译器会自己进行推断参数...也不行,道理是一样,只要lambda有用到这个变量,那这个变量不管是在哪里被修改,都是不允许 不然的话,这边先执行了一次lambda表达式,结果你就改了变量值,那我第二次执行lambda,不就乱了吗...类实例方法) 构造引用:就一种,编译器自己可判断是哪个构造函数,语法为Class::new 在lambda中引入外部变量,必须保证这个变量是最终变量,即不再被修改 lambda组合操作,就是链式操作

41610

Actors

第一种,在定义 actor 同一模块中,允许对某个不可变状态进行跨actor引用,因为一旦 actor 初始化完成,该不可变状态永远不会改变(无论从外部还是内部调用),所以这里在定义就杜绝了数据竞争...例如,如果我们想把存款存到账户account,我们可以在另一个 actor 中调用deposit(amount:),在另一个 actor 中,该调用会变成一条消息存在邮箱里,并且调用方会挂起。...然而,这意味着交叉任务改变状态, actor-isolated 状态可以在await中改变,这意味着开发人员必须确保在等待中破坏不变量。...通常来说,这就是异步调用需要await原因,因为调用挂起,各种不同状态(比如全局状态)都可能被改变。...这样地方有: 某个声明(比如函数体)定义引用另一个声明,例如调用函数,访问属性,或者计算下标。 一个声明满足某个协议要求。 我们下面具体讨论这两个场景。

1.2K51

C++11-右值引用类功能可变参数列表

,而空间中存放内容也都相同,相当于创建了三个内容完全相同对象,对于空间是一种浪费,程序效率也会降低,而且临时对象确实作用不是很大 左值引用短板: 但是函数返回对象是一个局部变量,出了函数作用域就不存在了...移动构造函数参数千万不能设置成const类型右值引用,因为资源无法转移而导致移动语义失效 在C++11中,编译器会为类默认生成一个移动构造,该移动构造为浅拷贝,因此类中涉及到资源管理,用户必须显式定义自己移动构造...,而产生额外开销,就好像转发者不存在一样 所谓完美就是函数模板在向其他函数传递自身形参,如果相应实参是左值,它就应该被转发为左值;如果相应实参是右值,它就应该被转发为右值 这样做是为了保留在其他函数针对转发而来参数左右值属性进行不同处理...11之前C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝构造函数 拷贝赋值重载 取地址重载 const 取地址重载 注意: 默认成员函数就是我们编译器会生成一个默认 C++11...即如何展开可变模版参数 由于语法不支持使用args[i]这样方式获取可变参数,所以我们用一些奇招来一一获取参数包值 1、参数包展开 递归函数方式展开参数包 示例: // 递归终止函数 template

80030

《Rust for Rustaceans》 样章试译 | 第二章 Rust 基础

借用检查器检查每条流每个顶点,并检查是否有其他兼容流同时存在。在这种情况下,借用检查器检查(3)处独占流,它会看到终止于(4)处共享流。...栈 栈是一个内存段,用于程序中函数调用暂存空间。每次调用函数,都会在栈顶分配一个称为帧(frame)连续内存块。靠近栈底部是主函数帧,函数调用其他函数,额外帧被压入栈。...堆 堆是一个内存池,与当前程序调用栈无关。在堆内存中值会一直存在,直到它们被明确地释放。当你想让一个值超过当前函数栈帧生存期,这很有用。...静态内存中值在程序整个执行过程中一直存在。程序静态内存包含程序二进制代码,通常被映射为只读。程序执行时,它会走查文本段(text-segment)中二进制代码每条指令,并在调用函数跳转。...这么做时候,可变引用后面的旧值会被立即析构。 最后,如果存在两个可变引用,那么可以在拥有其中任何一个情况下交换它们值(如(4)处)。

5.3K31

Python学习笔记之函数参数传递 值还是引用

在学完Python函数那一章节时,很自然就会想到Python中函数值呢?还是引用?或者都不是? ...原来值为1int型对象仍然存在,但我们不能再通过a这个标识符去访问它了(一个对象没有任何标签或引用指向它,它就会被自动释放)。...看下面示例: a = 1 # a指向内存中一个int型对象 a = 2 # 重新赋值 将a重新赋值,因为原来值为1对象是不能改变,所以a会指向一个新int对象,其值为2...那么Python中参数传递是值,还是引用呢?准确回答:都不是。之所以不是值,因为没有产生复制,而且函数拥有与调用者同样对象。而似乎更像是C++引用,但是有时却不能改变实参值。...所以只能这样说:对于不可变对象,它看起来像C++中值方式;对于可变对象,它看起来像C++中引用传递。 参考

1.9K30

Java8中Lambda表达式

1. lambda语法 下面分别说下语法中三个组成部分 参数: ( Dog dog ) 参数类型可省略(编译器可以自动推导),比如Comparator comparatorTest...@FunctionalInterface可以省略,但是建议加上,就是为了告诉编译器,这是一个函数式接口,此时如果该接口有多个抽象方法,那么编译器就会报错 反例:比如A extends B,A和B各有一个抽象方法...什么是构造引用 上面介绍了方法引用,就是直接引用某个方法 这里构造引用同理可得,就是引用某个类构造方法 构造引用表达式为:Class::new,仅此一种 如果你有多个构造函数,那编译器会自己进行推断参数...也不行,道理是一样,只要lambda有用到这个变量,那这个变量不管是在哪里被修改,都是不允许 不然的话,这边先执行了一次lambda表达式,结果你就改了变量值,那我第二次执行lambda,不就乱了吗...(类实例方法) 构造引用:就一种,编译器自己可判断是哪个构造函数,语法为Class::new 在lambda中引入外部变量,必须保证这个变量是最终变量,即不再被修改 lambda组合操作,就是链式操作

30210

C++11『右值引用 ‖ 完美转发 ‖ 新增类功能 ‖ 可变参数模板』

,直接将 临时对象 优化掉,尽量减少拷贝,这才有了 to_string() 函数中最终看到 一次拷贝构造 / 一次移动构造 言归正传,得益于 移动构造,临时对象 资源得到了回收利用,值返回不再需要经过无意义且低效...,可以将函数参数类型写为 T&&,因为模板具有自动推导特性,传入参数为 左值 ,触发 引用折叠 机制,实际参数类型会变为 T&;传入参数为 右值 ,正常使用 T&& 就行了 这一机制在模板中称为...简单来说就是 右值属性转早了 解决问题核心在于 perfectForward 传递 val 参数如何保证它 右值属性 丢失 2.2.参过程中保持右值属性 要想在参数传递过程中保持其 右值属性...; return 0; } 执行结果为 两次深拷贝 第一次深拷贝为构造触发(默认构造是 右值),第二次则是插入时触发(插入也是 右值) 这里在 构造 / 插入 使用可是 右值 啊,为什么...defalut 指定编译器自动生成 移动构造 Test(Test&&) = default; // 指定生成移动构造 再次运行程序,可以看到传入 右值 进行构造调用是 移动构造 这里想强调

27350

rust闭包(Closure)

闭包(Closure) 闭包在现代化编程语言中普遍存在。闭包是一种匿名函数,它可以赋值给变量也可以作为参数传递给其它函数,不同于函数是,它允许捕获调用者作用域中值。...捕获引用或者移动所有权 闭包可以通过三种方式捕获作用域中值,它们直接对应到函数获取参数三种方式:不可变借用,可变借用和获取所有权。闭包会根据函数体中如何使用被捕获值决定用哪种方式捕获。...最后一次调用lambda时候,其中存在x可变引用,而之前x.push_str又是一个可变引用。具体报错如下所示: 报错中很直接指出既有mutable又有immutable。 2....另外我们在调用了lambda之后,又使用了push_str来修改x,编译成功通过。这是因为rust编译器检测到lambda不再使用,直接被drop掉了。...在实际项目中,建议先使用 Fn 特征,然后编译器告诉你正误以及该如何选择。 参考资料 Rust语言圣经 Rust 程序设计语言

61020

【C语言】卍字通晓→函数+递归

printf 函数已提到过,这里从函数调用角度再强调一下。 调用函数,有两种向函数传递参数方式,如下↓ 调用函数传递参数调用方法,把参数实际值复制给函数形式参数。...址(引用)调用  通过指针传递方式,形参为指向实参地址指针,对形参指向操作,就相当于对实参本身进行操作。 ...函数声明和定义  函数声明就是告诉编译器这里是有一个函数,它参数和返回类型也要告诉编译器,那么这就够了。这个时候编译器就知道你这个函数已经声明了,就不会再不知道你没有这个函数。...函数声明就是在告知编译器有这个函数! 注意:声明只是告诉你有没有这个函数,真正取决于是函数定义! ...存在限制条件,满足这个限制条件之后时候,递归便会不再继续。 每次递归调用之后都会越来越接近这个限制条件。 这两个条件是必须要知道,这样你才知道递归怎么去使用。

72310

《C++Primer》第十六章 模板与泛型编程

大多数类型(除了unique_ptr和IO类型外)都是允许拷贝,但是不允许拷贝类型也是存在,而且使用常量引用在处理大对象也可以使函数运行地更快。...是底层,不是顶层 5.1 从左值引用函数参数推断类型 一个函数参数是模板类型参数一个普通(左值)引用时(即形如T&),绑定规则告诉我们只能给它一个左值(比如一个变量或者一个返回引用类型表达式)...一个函数参数是一个右值引用(即形如T&&),正常绑定规则告诉我们可以传递给它一个右值: template void f3(T&&); f3(42); // 实参是一个int...,但是非可变参数模板比可变参数模板更加特例化,因此编译器选择非可变参数版本 定义可变参数版本print,非可变参数版本声明必须在作用域中,否则可变参数版本会无限递归 3....compare一个字符串字面常量或者一个数组编译器才会调用第二个版本,如果我们传递给它字符指针,就会调用第一个版本(我们无法将一个指针转换为一个数组引用): const char *p1 = "hi

1.7K10

C++引用分析实例与案例刨析及使用场景分析详解

; cout << "c = " << c << endl; system("pause"); return 0; } 引用函数参数 作用:函数,可以利用引用技术让形参修饰实参 优点...引用语法更清楚简单 PS:值传递与地址传递回顾: 值传递 所谓值传递,就是函数调用时实参将数值传入给形参 值传递,==如果形参发生,并不会影响实参== 示例: void swap(int num1...注意:别名可以和原名相同 引用函数返回值 分析 作用:引用是可以作为函数返回值存在 注意:不要返回局部变量引用 用法:函数调用作为左值 示例 //返回局部变量引用 int& test01() {...如下图例子返回是a一个别名,再用一个别名ref去接收函数返回别名,最终ref是a一个别名。 上图结果:第二次输出就是乱码了,编译器不再保留改函数栈区数据a地址!...​ 只读不可修改,防止误操作 demo2指针常量,地址可变,值不可变 ​ 用于在函数体内给函数体外变量更换别名,且别名只在函数体内有效 demo3常量指针,地址不变,值可以变 ​ 正常值传递,可以简化指针值传递繁琐操作

25720

Rust学习笔记之所有权

这就意味着: 使用内存由「操作系统」在「运行时动态分配」出来 「使用完」String,需要通过某种方式将这些内存归还给操作系统 这里第一步由程序编写者,在调用String::from完成,这个函数会请求自己需要内存空间...Rust在变量离开作用域,会调用一个叫做drop特殊函数。「Rust会在作用域结束地方自动调用drop函数」。...} ❝变量所有权总是遵循相同模式:「将值赋给另一个变量移动它」 「持有堆中数据值变量离开作用域」,其值将通过 drop 被清理掉,除非数据被移动为另一个变量所有。...然后必须在调用 change 函数地方创建一个可变引用 &mut s,并更新函数签名以接受一个可变引用 some_string: &mut String。...这就非常清楚地表明,change 函数将改变它所借用值。 ❝不过可变引用有一个很大限制:在「同一间,只能有一个对某一特定数据可变引用」。

57810

分析CVE-2019-0708(BlueKeep)

接下来需要弄清楚如何调用函数,以及如何将通道名称设置为MS_T120。 在IcaBindVirtualChannels上设置了一个断点,就在调用IcaFindChannelByName地方。...在这种情况下,函数失败并导致创建MS_T120通道。要触发错误,需要第二次调用IcaBindVirtualChannels,MS_T120作为频道名称。...但是,使用易受攻击IcaBindVirtualChannels代码绑定它,它将与另一个id绑定。 补丁前后代码差异 本质上,MS_T120通道被绑定两次(一次在内部,然后由我们一次)。...由于通道绑定在两个不同id下,我们得到两个单独引用使用一个引用来关闭通道,将删除引用,通道也是如此; 但是,另一个参考仍然存在(称为免费使用后)。...使用剩余引用,现在可以编写不再属于我们内核内存。

76040
领券