超多有用的c++面试点笔记

1. 指针与引用的区别
  • 指针与引用看上去完全不同(指针用操作符"*“和”->“,引用使用操作符”."),但是它们似乎有相同的功能。指针和引用都是让你间接引用其它对象。

  • **在任何情况下都不能使用指向空值的引用。**一个引用必须总是指向某些对象。在C++里,引用应被初始化。

  • 不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高因为在使用引用之前不需要测试它的合法性。

  • 指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变。

总的来说,在以下情况下你应该使用指针:

  • 一是你考虑到存在不指向任何对象的可能(在这种情况下,你能够设置指针为空);
  • 二是你需要能够在不同的时刻指向不同的对象(在这种情况下,你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。

当你知道你必须指向一个对象并且不想改变其指向时,或者在重载操作符并为防止不必要的语义误解时(最普通的例子是操作符[]),你不应该使用指针。而在除此之外的其它情况下,则应使用指针。

2. **尽量使用C++**风格的类型转换

C++通过引进四个新的类型转换(cast)操作符克服了C风格类型转换的缺点。这四个操作符是:static_cast、const_cast、dynamic_cast、reinterpret_cast

  • static_cast在功能上基本上与C风格的类型转换一样强大,含义也一样。另外,static_cast不能从表达式中去除const属性,因为另一个新的类型转换操作符const_cast有这样的功能。

  • const_cast用于类型转换掉表达式的const或volatileness属性。如果你试图使用const_cast来完成修改constness或者volatileness属性之外的事情,你的类型转换将被拒绝。

  • **dynamic_cast被用于安全地沿着类的继承关系向下进行类型转换。**这就是说,你能用dynamic_cast把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用,而且你能知道转换是否成功。失败的转换将返回空指针(当对指针进行类型转换时)或者抛出异常(当对引用进行类型转换时)。

  • reinterpret_cast使用这个操作符的类型转换,其转换结果几乎都是执行期定义(implementation-defined)。因此,使用reinterpret_cast的代码很难移植。此操作符最普通的用途就是在函数指针之间进行转换。

3. 不要对数组使用多态

C++允许你通过基类指针和引用来操作派生类数组。不过这根本就不是一个特性,因为这样的代码几乎从不如你所愿地那样运行。数组与多态不能用在一起。

4. 避免无用的缺省构造函数

构造函数能初始化对象,而缺省构造函数则可以不利用任何在建立对象时的外部数据就能初始化对象。有时这样的方法是不错的。例如一些行为特性与数字相仿的对象被初始化为空值或不确定的值也是合理的,还有比如链表、哈希表、图等等数据结构也可以被初始化为空容器。但不是所有的对象都属于上述类型,对于很多对象来说,不利用外部数据进行完全的初始化是不合理的。比如一个没有输入姓名的地址薄对象,就没有任何意义。

利用指针数组代替一个对象数组这种方法有两个缺点:

  • 第一你必须删除数组里每个指针所指向的对象。如果忘了,就会发生内存泄漏。
  • 第二增加了内存分配量,因为正如你需要空间来容纳EquipmentPiece对象一样,你也需要空间来容纳指针。

对于类里没有定义缺省构造函数还会造成它们无法在许多基于模板(template-based)的容器类里使用。因为实例化一个模板时,模板的类型参数应该提供一个缺省构造函数。在多数情况下,通过仔细设计模板可以杜绝对缺省构造函数的需求。

5. 谨慎定义类型转换函数

C++编译器能够在两种数据类型之间进行隐式转换(implicit conversions),它继承了C语言的转换方法,例如允许把char隐式转换为int和从short隐式转换为double。你对这些类型转换是无能为力的,因为它们是语言本身的特性。不过当你增加自己的类型时,你就可以有更多的控制力,因为你能选择是否提供函数让编译器进行隐式类型转换。

有两种函数允许编译器进行这些的转换单参数构造函数(single-argument constructors)和隐式类型转换运算符。单参数构造函数是指只用一个参数即可调用的构造函数。该函数可以是只定义了一个参数,也可以是虽定义了多个参数但第一个参数以后的所有参数都有缺省值。

隐式类型转换运算符只是一个样子奇怪的成员函数:operator关键字,其后跟一个类型符号。你不用定义函数的返回类型,因为返回类型就是这个函数的名字。

explicit关键字是为了解决隐式类型转换而特别引入的这个特性。如果构造函数用explicit声明,编译器会拒绝为了隐式类型转换而调用构造函数。显式类型转换依然合法。

6. 自增(increment)、自减(decrement)操作符前缀形式与后缀形式的区别

无论是increment或decrement的前缀还是后缀都只有一个参数,为了解决这个语言问题,C++规定后缀形式有一个int类型参数,当函数被调用时,编译器传递一个0作为int参数的值给该函数。

前缀形式有时叫做”增加然后取回”,后缀形式叫做”取回然后增加”。

当处理用户定义的类型时,尽可能地使用前缀increment,因为它的效率较高。

7. **不要重载”&&”, “||”,**或”,”

与C一样,C++使用布尔表达式短路求值法(short-circuit evaluation)。这表示一旦确定了布尔表达式的真假值,即使还有部分表达式没有被测试,布尔表达式也停止运算。

C++允许根据用户定义的类型,来定制&&和||操作符。方法是重载函数operator&&和operator||,你能在全局重载或每个类里重载。风险:你以函数调用法替代了短路求值法。函数调用法与短路求值法是绝对不同的。首先当函数被调用时,需要运算其所有参数。第二是C++语言规范没有定义函数参数的计算顺序,所以没有办法知道表达式1与表达式2哪一个先计算。完全可能与具有从左参数到右参数计算顺序的短路计算法相反。因此如果你重载&&或||,就没有办法提供给程序员他们所期望和使用的行为特性,所以不要重载&&和||。

同样的理由也适用于逗号操作符。逗号操作符用于组成表达式。一个包含逗号的表达式首先计算逗号左边的表达式,然后计算逗号右边的表达式;整个表达式的结果是逗号右边表达式的值。如果你写一个非成员函数operator,你不能保证左边的表达式先于右边的表达式计算,因为函数(operator)调用时两个表达式作为参数被传递出去。但是你不能控制函数参数的计算顺序

所以非成员函数的方法绝对不行。**成员函数operator,你也不能依靠于逗号左边表达式先被计算的行为特性,因为编译器不一定必须按此方法去计算。**因此你不能重载逗号操作符,保证它的行为特性与其被料想的一样。重载它是完全轻率的行为。

8. 理解各种不同含义的new和delete

new操作符(new operator)和new操作(operator new)的区别:

new操作符就像sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为。你所能改变的是如何为对象分配内存。new操作符调用一个函数来完成必须的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是operator new。

函数operator new通常声明:返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。参数size_t确定分配多少内存。你能增加额外的参数重载函数operator new,但是第一个参数类型必须是size_t。就像malloc一样,operator new的职责只是分配内存。它对构造函数一无所知。把operator new返回的未经处理的指针传递给一个对象是new操作符的工作。

placement new:特殊的operator new,接受的参数除了size_t外还有其它。

new操作符(new operator)与operator new关系:你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。如果你仅仅想分配内存,就应该调用operator new函数,它不会调用构造函数。如果你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。如果你想在一块已经获得指针的内存里建立一个对象,应该用placement new。

Deletion and Memory Deallocation:为了避免内存泄漏,每个动态内存分配必须与一个等同相反的deallocation对应。函数operator delete与delete操作符的关系与operator new与new操作符的关系一样。

如果你用placement new在内存中建立对象,你应该避免在该内存中用delete操作符。因为delete操作符调用operator delete来释放内存,但是包含对象的内存最初不是被operator new分配的,placement new只是返回转到给它的指针。

Arrays:operator new[]、operator delete[]

9. 使用析构函数防止资源泄漏

用一个对象存储需要被自动释放的资源,然后依靠对象的析构函数来释放资源,这种思想不只是可以运用在指针上,还能用在其它资源的分配和释放上。

资源应该被封装在一个对象里,遵循这个规则,你通常就能够避免在存在异常环境里发生资源泄漏,通过智能指针的方式。

C++确保删除空指针是安全的,所以析构函数在删除指针前不需要检测这些指针是否指向了某些对象。

10. 在构造函数中防止资源泄漏

C++仅仅能删除被完全构造的对象(fully constructed objects),只有一个对象的构造函数完全运行完毕,这个对象才被完全地构造。C++拒绝为没有完成构造操作的对象调用析构函数。

在构造函数中可以使用try catch throw捕获所有的异常。更好的解决方法是通过智能指针的方式。

如果你用对应的std::unique_ptr对象替代指针成员变量,就可以防止构造函数在存在异常时发生资源泄漏,你也不用手工在析构函数中释放资源,并且你还能像以前使用非const指针一样使用const指针,给其赋值。

11. **禁止异常信息(exceptions)**传递到析构函数外

禁止异常传递到析构函数外有两个原因:第一能够在异常传递的堆栈辗转开解(stack-unwinding)的过程中,防止terminate被调用。第二它能帮助确保析构函数总能完成我们希望它做的所有事情。

12. **理解”**抛出一个异常”与”传递一个参数”或”调用一个虚函数”间的差异

你调用函数时,程序的控制权最终还会返回到函数的调用处,但是当你抛出一个异常时,控制权永远不会回到抛出异常的地方。

C++规范要求被作为异常抛出的对象必须被复制。即使被抛出的对象不会被释放,也会进行拷贝操作。抛出异常运行速度比参数传递要慢。

当异常对象被拷贝时,拷贝操作是由对象的拷贝构造函数完成的。该拷贝构造函数是对象的静态类型(static type)所对应类的拷贝构造函数,而不是对象的动态类型(dynamic type)对应类的拷贝构造函数。

catch子句中进行异常匹配时可以进行两种类型转换:第一种是继承类与基类间的转换。一个用来捕获基类的catch子句也可以处理派生类类型的异常。这种派生类与基类(inheritance_based)间的异常类型转换可以作用于数值、引用以及指针上。第二种是允许从一个类型化指针(typed pointer)转变成无类型指针(untyped pointer),所以带有const void*指针的catch子句能捕获任何类型的指针类型异常。

catch子句匹配顺序总是取决于它们在程序中出现的顺序。因此一个派生类异常可能被处理其基类异常的catch子句捕获,即使同时存在有能直接处理该派生类异常的catch子句,与相同的try块相对应。不要把处理基类异常的catch子句放在处理派生类异常的catch子句的前面。

把一个对象传递给函数或一个对象调用虚拟函数与把一个对象作为异常抛出,这之间有三个主要区别:第一,异常对象在传递时总被进行拷贝;当通过传值方式捕获时,异常对象被拷贝了两次。对象作为参数传递给函数时不一定需要被拷贝。第二,对象作为异常被抛出与作为参数传递给函数相比,前者类型转换比后者要少(前者只有两种转换形式)。最后一点,catch子句进行异常类型匹配的顺序是它们在源代码中出现的顺序,第一个类型匹配成功的catch将被用来执行。当一个对象调用一个虚拟函数时,被选择的函数位于与对象类型匹配最佳的类里,即使该类不是在源代码的最前头。

13. **通过引用(reference)**捕获异常

通过指针捕获异常不符合C++语言本身的规范。四个标准的异常:

  • bad_alloc(当operator new不能分配足够的内存时被抛出);
  • bad_cast(当dynamic_cast针对一个引用(reference)操作失败时被抛出);
  • bad_typeid(当dynamic_cast对空指针进行操作时被抛出);
  • bad_exception(用于unexpected异常)-都不是指向对象的指针,所以你必须通过值或引用来捕获它们。
14. 审慎使用异常规格(exception specifications)

如果一个函数抛出一个不在异常规格范围里的异常,系统在运行时能够检测出这个错误,然后一个特殊函数std::unexpected将被自动地调用(This function is automatically called when a function throws an exception that is not listed in its dynamic-exception-specifier.)。std::unexpected缺省的行为是调用函数std::terminate,而std::terminate缺省的行为是调用函数abort。应避免调用std::unexpected。

避免在带有类型参数的模板内使用异常规格。

C++允许你用其它不同的异常类型替换std::unexpected异常,通过std::set_unexpected。

15. 了解异常处理的系统开销

采用不支持异常的方法编译的程序一般比支持异常的程序运行速度更快所占空间也更小。

为了减少开销,你应该避免使用无用的try块。如果使用try块,代码的尺寸将增加并且运行速度也会减慢。

19. 理解临时对象的来源

在C++中真正的临时对象是看不见的,它们不出现在你的源代码中。建立一个没有命名的非堆(non-heap)对象会产生临时对象。这种未命名的对象通常在两种条件下产生:为了使函数成功调用而进行隐式类型转换和函数返回对象时。

仅当通过传值(by value)方式传递对象或传递常量引用(reference-to-const)参数时,才会发生这些类型转换。当传递一个非常量引用(reference-to-non-const)参数对象,就不会发生。

C++语言禁止为非常量引用(reference-to-non-const)产生临时对象。

临时对象是有开销的,所以你应该尽可能地去除它们。在任何时候只要见到常量引用(reference-to-const)参数,就存在建立临时对象而绑定在参数上的可能性。在任何时候只要见到函数返回对象,就会有一个临时对象被建立(以后被释放)。

20. 协助完成返回值优化

一些函数(operator*也在其中)必须要返回对象。这就是它们的运行方法。

C++规则允许编译器优化不出现的临时对象(temporary objects out of existence)。

21. 通过重载避免隐式类型转换

在C++中有一条规则是每一个重载的operator必须带有一个用户定义类型(user-defined type)的参数。

利用重载避免临时对象的方法不只是用在operator函数上。

没有必要实现大量的重载函数,除非你有理由确信程序使用重载函数以后其整体效率会有显著的提高。

22. **考虑用运算符的赋值形式(op=)**取代其单独形式(op)

就C++来说,operator+、operator=和operator+=之间没有任何关系,因此如果你想让三个operator同时存在并具有你所期望的关系,就必须自己实现它们。同理,operator-, *, /, 等等也一样。

确保operator的赋值形式(assignment version)(例如operator+=)与一个operator的单独形式(stand-alone)(例如operator+)之间存在正常的关系,一种好方法是后者(指operator+)根据前者(指operator+=)来实现。

24. 理解虚拟函数、多继承、虚基类和RTTI所需的代码

当调用一个虚拟函数时,被执行的代码必须与调用函数的对象的动态类型相一致;指向对象的指针或引用的类型是不重要的。大多数编译器是使用virtual table和virtual table pointers,通常被分别地称为vtbl和vptr。

一个vtbl通常是一个函数指针数组。(一些编译器使用链表来代替数组,但是基本方法是一样的)在程序中的每个类只要声明了虚函数或继承了虚函数,它就有自己的vtbl,并且类中vtbl的项目是指向虚函数实现体的指针。

你必须为每个包含虚函数的类的virtual table留出空间。类的vtbl的大小与类中声明的虚函数的数量成正比(包括从基类继承的虚函数)。每个类应该只有一个virtual table,所以virtual table所需的空间不会太大,但是如果你有大量的类或者在每个类中有大量的虚函数,你会发现vtbl会占用大量的地址空间。

一些原因导致现在的编译器一般总是忽略虚函数的inline指令。

Virtual table只实现了虚拟函数的一半机制,如果只有这些是没有用的。只有用某种方法指出每个对象对应的vtbl时,它们才能使用。这是virtual table pointer的工作,它来建立这种联系。每个声明了虚函数的对象都带着它,它是一个看不见的数据成员,指向对应类的virtual table。这个看不见的数据成员也称为vptr,被编译器加在对象里,位置只有编译器知道。

虚函数是不能内联的。这是因为”内联”是指”在编译期间用被调用的函数体本身来代替函数调用的指令”,但是虚函数的”虚”是指”直到运行时才能知道要调用的是哪一个函数”。

RTTI(运行时类型识别)能让我们在运行时找到对象和类的有关信息,所以肯定有某个地方存储了这些信息让我们查询。这些信息被存储在类型为type_info的对象里,你能通过使用typeid操作符访问一个类的type_info对象。

25. 将构造函数和非成员函数虚拟化

虚拟构造函数是指能够根据输入给它的数据的不同而建立不同类型的对象。虚拟拷贝构造函数能返回一个指针,指向调用该函数的对象的新拷贝。类的虚拟拷贝构造函数只是调用它们真正的拷贝构造函数。被派生类重定义的虚拟函数不用必须与基类的虚拟函数具有一样的返回类型。如果函数的返回类型是一个指向基类的指针(或一个引用),那么派生类的函数可以返回一个指向基类的派生类的指针(或引用)。

27. 要求或禁止在堆中产生对象

禁止堆对象:禁止用于调用new,利用new操作符总是调用operator new函数这点来达到目的,可以自己声明这个函数,而且你可以把它声明为private。

28. **灵巧(smart)**指针

灵巧指针是一种外观和行为都被设计成与内建指针相类似的对象,不过它能提供更多的功能。它们有许多应用的领域,包括资源管理和重复代码任务的自动化。

在C++11中auto_ptr已经被废弃,用unique_ptr替代。

29. 引用计数

引用计数是这样一个技巧,它允许多个有相同值的对象共享这个值的实现。这个技巧有两个常用动机。第一个是简化跟踪堆中的对象的过程。一旦一个对象通过调用new被分配出来,最要紧的就是记录谁拥有这个对象,因为其所有者----并且只有其所有者----负责对这个对象调用delete。但是,所有权可以被从一个对象传递到另外一个对象(例如通过传递指针型参数)。引用计数可以免除跟踪对象所有权的担子,因为当使用引用计数后,对象自己拥有自己。当没人再使用它时,它自己自动销毁自己。因此,引用计数是个简单的垃圾回收体系。第二个动机是由于一个简单的常识。如果很多对象有相同的值,将这个值存储多次是很无聊的。更好的办法是让所有的对象共享这个值的实现。这么做不但节省内存,而且可以使得程序运行更快,因为不需要构造和析构这个值的拷贝。

实现引用计数不是没有代价的。每个被引用的值带一个引用计数,其大部分操作都需要以某种形式检查或操作引用计数。对象的值需要更多的内存,而我们在处理它们时需要执行更多的代码。引用计数是基于对象通常共享相同的值的假设的优化技巧。如果假设不成立的话,引用计数将比通常的方法使用更多的内存和执行更多的代码。另一方面,如果你的对象确实有具有相同值的趋势,那么引用计数将同时节省时间和空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/685421.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录刷题笔记-Day17

1. 路径总和 112. 路径总和https://leetcode.cn/problems/path-sum/ 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true …

【蓝桥杯 2021】图像模糊

图像模糊 题目描述 小蓝有一张黑白图像,由 nm 个像素组成,其中从上到下共 n 行,每行从左到右 m 列。每个像素由一个 0 到 255 之间的灰度值表示。 现在,小蓝准备对图像进行模糊操作,操作的方法为: 对于…

循序渐进-讲解Markdown进阶(Mermaid绘图)-附使用案例

Markdown 进阶操作 查看更多学习笔记:GitHub:LoveEmiliaForever Mermaid官网 由于CSDN对某些Mermaid或Markdown语法不支持,因此我的某些效果展示使用图片进行 下面的笔记内容全部是我根据Mermaid官方文档学习的,因为是初学者所以…

防火墙工作模式详解

防火墙工作模式是指防火墙在网络中的工作方式和策略。常见的防火墙工作模式包括以下几种: 1. 包过滤工作模式:根据事先确定的规则集合,对进出网络的网络包进行过滤和检查。根据规则,防火墙可以允许或阻止特定的网络流量。 2. 代…

记录 | windows pyqt5 pycharm配置

一、下载安装 离线安装 通过PyPI下载 https://pypi.org/ 依此搜索 python_dotenv,PyQt5_sip,PyQt5,pyqt5_tools,注意PyQt5和pyqt5_tools版本对应。 下载之后放在\Anaconda3\Lib\site-packagescmd依次 pip install *.whl 二…

人工智能学习与实训笔记(十四):Langchain Agent

0、概要 Agent是干什么的? Agent的核心思想是使用语言模型(LLM)作为推理的大脑,以制定解决问题的计划、借助工具实施动作。在agents中几个关键组件如下: Agent:制定计划和思考下一步需要采取的行动。Tools…

跟着pink老师前端入门教程-day27

三、变量 (一)变量概述 1、什么是变量 白话:变量就是一个装东西的盒子 通俗:变量是用于存放数据的容器,通过变量名获取数据,甚至数据可以修改 2、变量在内存中的存储 本质:变量是程序在内存…

Java毕业设计-基于ssm的网上餐厅管理系统-第72期

获取源码资料,请移步从戎源码网:从戎源码网_专业的计算机毕业设计网站 项目介绍 基于ssm的网上餐厅管理系统:前端jsp、jquery、bootstrap,后端 maven、springmvc、spring、mybatis,集成类名管理、菜品管理、订单管理…

(17)Hive ——MR任务的map与reduce个数由什么决定?

一、MapTask的数量由什么决定? MapTask的数量由以下参数决定 文件个数文件大小blocksize 一般而言,对于每一个输入的文件会有一个map split,每一个分片会开启一个map任务,很容易导致小文件问题(如果不进行小文件合并&…

C# CAD 框选pdf输出

在C#中进行AutoCAD二次开发时,实现框选(窗口选择)实体并输出这些实体到PDF文件通常涉及以下步骤: public ObjectIdCollection GetSelectedEntities() {using (var acTrans HostApplicationServices.WorkingDatabase.Transaction…

代码随想录算法训练营29期Day52|LeetCode 198,213,337

文档讲解:打家劫舍 打家劫舍II 打家劫舍III 198.打家劫舍 题目链接:https://leetcode.cn/problems/house-robber/description/ 思路: 设dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金…

Sora:AI视频生产力的颠覆性跃进,让创意瞬间成“视界”!

在AI视频技术宇宙中,RunwayGen2、Stable Video Diffusion和Pika等明星产品早已名声在外。然而,今日横空出世的Sora犹如一颗璀璨新星,以其震撼性的创新突破,在视频制作领域掀起了一场革命!相较于市面上同类AI视频神器&a…

【洛谷 P3367】【模板】并查集 题解(并查集+启发式合并)

【模板】并查集 题目描述 如题,现在有一个并查集,你需要完成合并和查询操作。 输入格式 第一行包含两个整数 N , M N,M N,M ,表示共有 N N N 个元素和 M M M 个操作。 接下来 M M M 行,每行包含三个整数 Z i , X i , Y i Z_i,X_i,Y…

力扣57题:插入区间

题目链接】 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 【解题代码】 class Solution {public int[][] insert(int[][] intervals, int[] newInterval) {List<int[]> intervalList new ArrayList<>();boolean newIntervalInsert …

使用 Mermaid 创建流程图,序列图,甘特图

使用 Mermaid 创建流程图和图表 Mermaid 是一个流行的 JavaScript 库&#xff0c;用于创建流程图、序列图、甘特图和其他各种图表。它的简洁语法使得创建图表变得非常简单&#xff0c;无需复杂的绘图工具或专业的编程技能。在本文中&#xff0c;我们将讲解如何使用 Mermaid 来创…

【动态规划】买卖股票问题

1.一次买入&#xff0c;一次卖出 买卖股票1 1.明确dp[i][0] dp[i][1]含义 dp[i][0]:表示可能在前i天(包括第i天)不持有该股票,产生的最大收益 dp[i][1]:表示可能在前i天(包括第i天)持有该股票,产生的最大收益 2.递推公式 dp[i][0]可能在i天之前卖出&#xff0c;所以的dp[i]…

android获取sha1

1.cmd在控制台获取 切换到Android Studio\jre\bin目录下执行keytool -list -v -keystore 签名文件路径例如&#xff1a; 2.也可以在android studio中获取 在Terminal中输入命令&#xff1a;keytool -list -v -keystore 签名文件路径获取 获取到的sha1如下&#xff1a;

理解并实现OpenCV中的图像平滑技术

导读 图像模糊&#xff08;也称为图像平滑&#xff09;是计算机视觉和图像处理中的基本操作之一。模糊图像通常是噪声减少、边缘检测和特征提取等应用的第一步。在本博客中&#xff0c;我们将重点介绍如何使用Python中的OpenCV库应用多种模糊技术。 理论概述&#xff1a; 基本…

【报告解析】OpenAI Sora视频模型官方报告全解析 | 效果,能力以及基本原理

省流版 1 核心数据处理将视频数据整合成一个一个的Patch&#xff0c;方便统一训练数据&#xff0c;利用扩散Transformer架构 2 功能效果除了可以实现基础的文生视频外&#xff0c;实际上还有非常惊艳的视频延展&#xff0c;视频编辑&#xff0c;视频连接等多种功能&#xff0…

Android 11.0 SystemUI禁用长按recent键的分屏功能

1.前言 在11.0的系统rom产品定制化中,系统对于多窗口模式默认会有分屏功能的,但是在某些产品中,需要禁用分屏模式,所以需要在导航栏中 禁用长按recent的分屏模式功能,接下来分析下相关分屏模式的实现 2.SystemUI禁用长按recent键的分屏功能的核心类 frameworks\base\…