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

为什么` `std::function`对象(即`fn`)在对象`ins`超出作用域后仍然可以正常工作?

std::function是C++11标准库中的一个函数对象封装器,它可以用来存储、复制和调用任何可调用对象,包括函数指针、函数对象、Lambda表达式等。

当一个std::function对象被创建时,它会通过复制或移动语义来拷贝或移动被存储的可调用对象。这意味着,std::function对象实际上拥有一个拷贝或移动的副本,而不是原始的可调用对象本身。

在C++中,当一个对象超出其作用域时,它的析构函数会被调用,用于清理对象的资源。对于std::function对象来说,它的析构函数会销毁所持有的可调用对象,释放相关资源。

然而,即使std::function对象所持有的可调用对象被销毁,它仍然可以正常工作的原因是,std::function对象内部实现了一个类型擦除机制。它将不同类型的可调用对象都转换为一个统一的接口,以便在调用时进行动态分发。

具体来说,std::function对象内部维护了一个函数指针和一个指向函数对象的指针。当调用std::function对象时,它会根据存储的可调用对象的类型,选择合适的调用方式。如果存储的是函数指针,它会直接调用函数指针;如果存储的是函数对象,它会通过指针调用函数对象的operator()

因此,即使原始的可调用对象被销毁,std::function对象仍然可以通过保存的函数指针或函数对象指针来调用相应的函数。这种机制使得std::function对象可以在其所持有的可调用对象超出作用域后继续正常工作。

总结起来,std::function对象在对象超出作用域后仍然可以正常工作的原因是它内部实现了类型擦除机制,通过保存函数指针或函数对象指针来调用相应的函数。这使得std::function对象具有灵活性和通用性,可以用于存储和调用各种类型的可调用对象。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

闭包 + 局部作用 === 如鱼得水

foo()函数以一个函数对象作为返回值。foo()函数执行,其返回值被赋值给了变量fn并调用fn()。实际上只是通过不同的标识符引用调用了这个被作为返回值的函数对象。...fn()可以正常执行,并且还是在被自己定义的词法作用之外执行。 这就是闭包的神奇了。...通常一个函数执行完毕其内部作用就会被销毁,但由于内部作用此时仍然被标识符fn所指向的函数对象所引用,所以foo()函数的内部作用不会被销毁,而这个引用就是闭包。...而当for循环执行完毕,变量i的值就是6。 虽然for循环出来了五个延迟函数,但是根据作用工作原理,这五个延迟函数是被封闭for循环所处的全局作用内的。这个全局作用域中的变量i此时值已是6。...所以五个延迟函数执行时都读到同一个值为6的变量i,最后结果最后打印结果也就是五个6。 理解上面的原因,需要理解两个知识点:js中同步异步的执行顺序原理、作用工作原理。

60030

《你不知道的JavaScript》:闭包与局部作用

foo()函数以一个函数对象作为返回值。foo()函数执行,其返回值被赋值给了变量fn并调用fn()。实际上只是通过不同的标识符引用调用了这个被作为返回值的函数对象。...fn()可以正常执行,并且还是在被自己定义的词法作用之外执行。 这就是闭包的神奇了。...通常一个函数执行完毕其内部作用就会被销毁,但由于内部作用此时仍然被标识符fn所指向的函数对象所引用,所以foo()函数的内部作用不会被销毁,而这个引用就是闭包。...而当for循环执行完毕,变量i的值就是6。 虽然for循环出来了五个延迟函数,但是根据作用工作原理,这五个延迟函数是被封闭for循环所处的全局作用内的。这个全局作用域中的变量i此时值已是6。...所以五个延迟函数执行时都读到同一个值为6的变量i,最后结果最后打印结果也就是五个6。 理解上面的原因,需要理解两个知识点:js中同步异步的执行顺序原理、作用工作原理。

52320
  • JS进阶第一天

    函数的参数也是函数内部的局部变量 不同函数内部声明的变量无法互相访问 函数执行完毕,函数内部的变量实际被清空了 块作用 JavaScript 中使用 {} 包裹的代码称为代码块,代码块内部声明的变量外部将...console.log(str); // 正常 } // 超出了 age 的作用 console.log(str); // 报错 for(let t = 1; t <= 6...; t++) { // t 只能在该代码块中被访问 console.log(t); // 正常 } // 超出了 t 的作用 console.log(t); // 报错...全局作用 标签和 .js 文件的【最外层】就是所谓的全局作用,在此声明的变量函数内部也可以被访问。...解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。

    69820

    this的理解

    this引用的是function的词法作用 存在这种误解的人可能更多一些。首先,this并没有引用function的词法作用。...的确JS的引擎内对词法作用的实现的确像是一个对象,拥有属性和函数,但是这仅仅是JS引擎的一种实现,对代码来说是不可见的,也就是说词法作用"对象"JS代码中取不到。...; } fn1(); [this作用.png] 上面的代码明显没有执行出想要的结果,从而可以看到this并没有引用函数的词法作用。...甚至,可以肯定的说,这个例子里fn2可以fn1里正确执行都是偶然的(理解了词法作用你就知道为什么这里执行不报错了)。...global : window); [this指向作用.png] bind() 对直接调用的影响 Function.prototype.bind()的作用是将当前函数与指定的对象绑定,并返回一个新函数

    52630

    JavaScript进阶-01

    函数的参数也是函数内部的局部变量 不同函数内部声明的变量无法互相访问 函数执行完毕,函数内部的变量实际被清空了 块作用 JavaScript 中使用 {} 包裹的代码称为代码块,代码块内部声明的变量外部将...console.log(str); // 正常 } // 超出了 age 的作用 console.log(str); // 报错 for(let t = 1; t <= 6...; t++) { // t 只能在该代码块中被访问 console.log(t); // 正常 } // 超出了 t 的作用 console.log(t); // 报错...1.2 全局作用 标签和 .js 文件的【最外层】就是所谓的全局作用,在此声明的变量函数内部也可以被访问。...解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。

    70520

    夯实JavaScript知识点一文足矣

    为什么基本类型却可以直接调用引用类型的方法呢?...(词法作用是在编译阶段就确认的,区别于词法作用,动态作用函数执行的时候确认的,js的没有动态作用,但js的this很像动态作用,后面会提到。...作用链本质上是一个指向变量对象的指针列表,它只引用不包含实际变量对象,是作用概念的延申。作用链定义了在当前上下文访问不到变量的时候如何沿作用链继续查询变量的一套规则。...建立执行上下文阶段:(发生在 函数被调用时 && 函数体内的代码执行前 ) 生成变量对象,顺序:创建 arguments 对象 --> 创建function函数声明 --> 创建var变量声明 生成作用链...利用call、apply、bind函数可以把函数的this变量指向第一个参数。 方法4中用new实例化了一个对象instance,这时fn中的this就指向了实例instance。

    52530

    通过vue.js 学习来总结es6语法中的箭头函数,箭头函数原理分析。

    为什么叫Arrow Function?...({ foo: x }) this    —— 笔者认为this是重点需要关注的学习目标 箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用...this的指向,this总是指向词法作用,也就是外层调用者obj: var obj = { birth: 1990, getAge: function () { var...由于this箭头函数中已经按照词法作用绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,传入的第一个参数被忽略: var obj = { birth:...//中this的指向一直是外层对象廖雪峰大神说的“箭头函数完全 //修复了this的指向,this总是指向词法作用,也就是外层调用者obj” } }) </

    1.6K20

    JavaScript 进阶 - 第1天

    函数的参数也是函数内部的局部变量 不同函数内部声明的变量无法互相访问 函数执行完毕,函数内部的变量实际被清空了 块作用 JavaScript 中使用 {} 包裹的代码称为代码块,代码块内部声明的变量外部将...; console.log(str); // 正常 } // 超出了 age 的作用 console.log(str); // 报错 for(let t = 1;...t <= 6; t++) { // t 只能在该代码块中被访问 console.log(t); // 正常 } // 超出了 t 的作用 console.log(t)... 标签和 .js 文件的【最外层】就是所谓的全局作用,在此声明的变量函数内部也可以被访问。...foo(); fn(); // 1 总结: 闭包:一个作用有权访问另外一个作用的局部变量, 好处:可以把一个变量使用范围延伸 闭包本质仍是函数,只不是从函数内部返回的

    80020

    Rust入坑指南:核心概念

    Ownership的规则 Rust中,每一个值都有对应的变量,这个变量称为值的owner 一个值某一时刻只能有一个owner 当owner超出作用,值会被销毁 这三条规则非常重要,记住他们会帮助你更好的理解本文...变量作用 Ownership的规则中,有一条是owner超过范围,值会被销毁。那么owner的范围又是如何定义的呢?Rust中,花括号通常是变量范围作用的标志。...Rust为了解决这一问题,执行let s2 = s1;这句代码时,认为s1已经超出作用右侧的内容的owner已经变成了s2,也可以说s1的ownership转移给了s2。...("{}", some_string); } // some_string 超出作用并调用了drop函数 // 内存被释放 那有没有办法执行takes_ownership函数使s继续生效呢?...主要有两点不同: 传入参数的时候,s1前面加了&符。这意味着我们创建了一个s1的引用,它并不是数据的owner,因此超出作用时也不会销毁数据。

    86420

    C++编程经验(12):C++11新特性

    除了能够适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。 使用对象的时候,使用强智能指针;引用对象的时候,使用弱智能指针。...---- using 现在不仅仅可以用它来引用名空间了,不过现在我也不怎么用这个来引用名空间了,都是用作用符::。...当修改完毕,再把修改的结果放回到主内存中。每个线程都只操作自己工作内存中的变量,无法直接访问对方工作内存中的变量,线程间变量值的传递需要通过主内存来完成。...它的特点如下: 创建加锁,作用结束自动析构并解锁,无需手工解锁 不能中途解锁,必须等作用结束才解锁 不能复制 ---- unique_lock 简单地讲,unique_lock 是 lock_guard...特点如下: 创建时可以不锁定(通过指定第二个参数为std::defer_lock),而在需要时再锁定 可以随时加锁解锁 作用规则同 lock_grard,析构时自动释放锁 不可复制,可移动 条件变量需要该类型的锁作为参数

    1K20

    37个JavaScript基本面试问题和解答(建议收藏)

    那么,因为声明var a = b = 3;是语句b = 3的简写;并且var a = b; b最终成为一个全局变量(因为它不在var关键字后面),因此它仍然作用内,即使封闭函数之外。...这是因为循环内执行的每个函数将在整个循环完成执行,因此所有函数都会引用存储i中的最后一个值,5。...通过为每次迭代创建一个唯一的作用可以使用闭包来防止这个问题,并将该变量的每个唯一值存储在其作用域中,如下所示: for (var i = 0; i < 5; i++) { (function...首先,由于fn作为函数方法的参数传递,函数fn作用(this)是窗口。 var length = 10;在窗口级别声明。...fn里面,这个函数的作用成为参数数组,并且记录参数[]的长度将返回2。 因此输出将如上所述。 28、考虑下面的代码。输出是什么,为什么

    3K10

    《你不知道的JavaScript》:this 绑定规则的例外情况与总结

    这里有个小知识点,针对上面展开数组的操作,ES6中可以通过...来代替apply(),fn(...[10, 4])和fn(10, 4)是一样的,这样能够避免非必要的this绑定。...// 2 bar.call( obj3 ); // 3 setTimeout(obj2.fn, 1000) // 1 可以看到,fn中this绑定到对象obj1,再将函数引用赋值给...obj2,修改函数fn的调用位置上下文对象为obj2时,可以实现修改this绑定,使用call()修改this绑定对象也能工作。...可以采用其他折中办法。 例外情况4: 箭头函数 ES6中,箭头函数对this的对象绑定作用机制完全不一样。箭头函数并不是使用function关键字定义的。而是根据 => 操作符定义的。...当然ES5中也可以使用词法作用来规避麻烦的this机制: function fn(){ var self = this; setTimeout(function(){

    49910

    面试最爱问的闭包问题!!!!

    JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来; 那么我的理解和总结: 一个普通的函数function,==如果它可以访问外层作用的自由变量,那么这个函数就是一个闭包...只有那些找不到的对象才是内存垃圾,才会在适当的时机被 gc 回收那什么是内存泄漏呢?内存泄漏是指:用动态存储分配函数内存空间,使用完毕未释放,导致一直占据该内存单元。直到程序结束。...指任何对象在你不再拥有或需要它之后仍然存在。...,因为bar函数内部进行了访问,因为JavaScript的内存回收机制中规定,被另一个作用引用的变量不会被回收。...fn.apply(this, args); }, time); };};结论绝大多数情况下,只要引用闭包的函数被正常销毁,闭包所占的内存都是会被 gc 自动回收的。

    26510

    万字干货!详解JavaScript执行过程

    var name = 'FinGet'; function fn() { var age = 18; console.log(name); } 解析时就会确定作用: 简单的来说,作用就是个盒子...myName = " global_finget " fn1() 上面代码打印的结果是:global_finget,这就是因为在编译阶段就已经确定了作用fn是定义全局作用域中的,它在自己内部找不到...ES6之前都没有块级作用,ES6之后我们可以用let const来声明块级作用,有这两个词法环境是为了实现块级作用的同时不影响var变量声明和函数声明,具体如下: 首先在一个正在运行的执行上下文内...其实,词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用,就会把该作用块内部的变量压到栈顶;当作用执行完成之后,该作用的信息就会从栈顶弹出,这就是词法环境的结构。...看这个图就可以看出作用链了吧,很直观。作用链就是执行上下文创建阶段确定的。有了执行的环境,才能确定它应该和谁构成作用链。

    1K40

    C++11的简单介绍(下)

    作用指包含lambda函数的语句块 b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。...作用以外的lambda函数捕捉列表必须为空。 e. 作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用或者非局部变量都会导致编译报错。...2.包装器 2.1 function包装器 function包装器 也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。那么我们来看看,我们为什么需要function呢?...这样实例化很麻烦 包装器可以很好的解决上面的问题: 包装器的模板如下: std::function头文件 // 类模板原型如下 template function...Args> bind (Fn&& fn, Args&&... args); 可以将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

    9410

    这次把 javascript 闭包给你讲的明明白白

    () { // var j = i; // 因为当前作用是没有i的,i作用之外,这样onclick就持有了该作用的引用,这个引用就叫做闭包 // var...() { alert('第' + (i + 1) + '个'); // 持有外部作用的引用,形成闭包 } } // 块作用和闭包联手便可以天下无敌...使用函数内部的变量函数执行完, 仍然存活在内存中(延长了局部变量的生命周期) 2. 让函数外部可以操作(读写)到函数内部的数据(变量/函数) 问题: 1....var a = hd.get(); // 执行get(),返回里面的function // this 总是指向调用该函数的对象函数搜索this时只会搜索到当前活动对象。...,函数搜索this时只会搜索到当前活动对象

    39900

    面向对象、this

    JavaScript中的变量作用非常重要,最后为this变量赋值,会根据函数调用方式的不同,赋给this全局对象,当前对象等 至此函数的执行环境(ExecutionContext)创建成功,函数开始逐行执行...console.log(this); function fn1(){ console.log(this); } fn1(); 全局环境中声明的变量、函数,都可以看成是window的属性、方法...(2)内部函数 函数嵌套产生的内部函数的this指的不是其父函数,仍然是全局对象。...由于this指向由构造函数创造的实例对象这里的p1,p2,p3。...(4)作为对象方法调用 JavaScript 中,函数也是对象,因此函数可以作为一个对象的属性,此时该函数被称为该对象的方法,使用这种调用方式时,this 自然指向该对象 var obj1 = {

    47730

    【Rust 基础篇】Rust 弱引用:解决引用循环与内存泄漏

    引用循环的问题 引用循环 Rust 中是指两个或多个对象之间相互引用,形成一个循环链。这种情况下,对象之间的引用计数永远不会变为零,导致内存泄漏和资源泄漏。...考虑以下示例: use std::rc::Rc; struct Node { data: i32, next: Option>, } fn main() {...注意,node1 和 node2 之间形成了引用循环, node1 引用了 node2,同时 node2 也引用了 node1,导致引用计数永远不会变为零。...由于引用循环的存在,当 node1 和 node2 超出作用时,它们的引用计数不会减少,无法正确释放内存,从而造成内存泄漏。...使用 Weak 引用时,我们需要注意在使用之前调用 upgrade 方法,以检查所指向的对象是否已被释放。如果 upgrade 方法返回 Some,说明所指向的对象仍然存在,可以安全地访问其数据。

    41920
    领券