《Effective C++》学习笔记

news2024/9/22 13:42:42

条款01:把 C++ 看成一个语言联邦


C++由几个重要的次语言构成

C语言:区块,语句,预处理器,数组,指针等等。

类:class,封装,继承,多态......(动态绑定等等)

模板:涉及泛型编程,内置数种可供套用的函数或者类。

STL:STL是个模板库,主要涉及容器,算法和迭代器

在不同情况下使用适合的部分,可以使 C++ 实现高效编程
 

条款02:尽量以const,enum,inline替换 #define

因为或许 #define 不被视为语言的一部分,这经常会产生让人捉摸不透的bug

1,#define 修饰的记号,在预处理的时候可能就替换成了对应的数值,当代码出错的时候会提到具体的数值,但是我们不知道这个数值是干什么的

解决之道:以一个常量替换上述的宏(#define)

const double AspectRatio = 1.653   //大写名称通常用于宏,因此这里改变名称写法

2.#define 无法创建一个 class 专属常量,因为 #define 不重视作用域。一旦宏被定义,那么它就在其后的编译过程中有效,它不提供任何封装性

//enum hack 补偿做法:
enum 枚举量{para1 = value1, para2 = value2,......}
//将一个枚举类型的数值当作 int 类型使用
//和 #define 很像,都不能取地址,但它没有 #define 的缺点

3.看看这个神奇的宏

template<typename T>
inline void callWithMax(const T& a,const T& b)  //由于不知道T是什么,所以采用 pass by reference-to-const
{
    f(a > b? a:b);
}
  • 对于单纯常量,最好以 const 对象或 enums 替换 #defines
  • 对于形似函数的宏(macros),最好改用 inline 函数替换#define

条款03:尽可能使用 const

const 允许你指定一个于一约束,使一个值不被改动

如果关键字 const 出现在星号左边,表示被指物是常量,如果出现在星号右边,表示指针自身是常量。如果出现在两边,表示都是常量

const 修饰迭代器

const 修饰成员函数

        如果两个成员函数只是常量性不同(其他相同)则可以发生重载

                const 类对象调用 const 成员函数

                non-const 类对象调用普通成员函数

bitwise:

const 成员函数不能改变(除 static)成员变量的值,因为常函数里 this 指针指向的值不可改变。同理,const 对象不可以调用 non-const 函数,因为函数有能力更改成员属性的值。

        但是若成员变量是一个指针,仅仅改变指针指向的值却不改变指针地址(地址是 this 指向的值),则不算是 const 函数 ,但能够通过 bitwise 测试。

        使用 mutable 可以消除 non-static 成员变量的 bitwise constness 约束。

3、当 const 和 non-const 成员函数有实质的等价实现时,利用两次转型,令 non-const 调用 const 可以避免代码重复。

const char& operator[](int pos) const
{
    //...
    //...
    return name[pos];
}
 
char& operator[](int pos)
{
    return
        const_cast<char&>//移除第一次转型添加的 const
            (
                static_cast<const classname>(*this)[pos]
                //把 classname 类型数据转换为 const classname
                //使得能够调用 const operator[]
            );
}

条款04:确定对象被使用前已先被初始化

具体规则比较复杂,最佳处理办法就是:永远在使用对象之前先将它初始化。对于无任何成员的内置类型,必须手工完成此事:

内置类型以外的任何其他类型,初始化责任落在构造函数身上

不要混淆了赋值和初始化

这会使对象带有你指定的值,并不是最佳的做法

如果成员变量是 const 或 reference,它们就一定需要初值,不能被赋值。为了避免需要记住成员变量合适必须在成员初值列中初始化,何时不需要,最简单的做法是:总是使用成员初值列。

class 的成员变量总是以其声明次序被初始化,即使更改初始值列表的次序也不影响

使用 local-static 对象替换 non-local-static 对象

函数内 static 对象是 local-static 对象,函数外 static 对象是 non-local-static 对象。

C++ 对 “定义于不同编译单元内的 non-local static 对象”的初始化次序并无明确定义

解决办法:利用一个函数,定义并初始化本 static 对象,并返回它的引用。类似于 singleton 设计模式,调用这个函数获得想要的对象引用,而不是直接获取这个对象引用

条款05:了解C++默默编写并调用哪些函数

惟有当这些函数被需要,它们才会被编译器创建出来。下面代码造成上述每一个函数被编译器产出:

拷贝运算符注意事项:

若成员变量中有引用,或者被 const 修饰等等,拷贝运算符不可被调用。

条款06:若不想使用编译器自动生成的函数,就该明确拒绝

编译器自动生成的函数都是 public 函数,所以我们将 public 改为 private,就可以防止对象调用拷贝构造。

注:private 只有成员函数和友元函数可以调用。

同时也产生了一个问题,如何防止拷贝在成员函数或友元函数中被调用?

答案是建立一个父类,在父类中定义 private 拷贝函数,子类( person 等等)继承父类。因为子类不可以调用父类的 private 函数:

条款07:为多态基类声明 virtual 析构函数

如果一个基类没有声明 virtual 析构函数,那么当销毁一个指向该基类的派生类的指针时就会造成诡异的局部销毁,派生的部分还残留着

给 base class 一个 virtual 析构函数,以后删除 derived class 对象就会如我们希望的那样销毁整个对象

当 class 不企图被当作 base class ,令其析构函数为 virtual 往往是个馊主意

如果类中含有 virtual 函数,其体积会增加

条款08:别让异常逃离析构函数

C++并不禁止析构函数吐出异常,但它不鼓励你这样做

在C++程序中,若是同时存在两个异常,则要么结束程序,要么导致不确定行为。结束程序,剩余的操作就无法完成,这对于程序员来说是一个麻烦。

异常处理方法:

try
{...}
//try 内部写可能产生异常的语句,没有产生异常,则catch语句不执行,产生则一一匹配
//catch 用于捕获并处理异常,和 case 有异曲同工之妙
catch(...)
{
    1、可以使用 abort(); 函数终止程序
    2、可以吞下这个异常,在 catch 内部做一些处理
}

条款09:绝不在构造和析构过程中调用 virtual 函数

众所周知,在类的操作中,父类比子类先构造,而子类也比父类先析构(多态也是如此,多态先通过 virtual 找到子类析构,再析构父类),所以在构造父类的时候,子类对象还未进行初始化,在析构父类的时候,子类已经被销毁。

此时,如果父类的构造和析构函数中有 virtual ,则该函数无法找到子类的地址(或者说无视子类,因为子类被销毁/未被初始化),使程序发生不明确的行为。

所以 virtual 函数的调用无法下降至子类,但是子类可以将必要的构造信息向上传递到父类:

条款10:令 operator= 返回一个 reference to *this

为了实现以上效果

条款11:在 operator= 中处理“自我赋值”

a[ i ] = a[ j ]      //如果 i == j 那么也是自我赋值

*px = *py      //潜在的自我赋值

一般而言如果某段代码操作 pointers 或 references 而被它们用来“指向多个相同类型的对象”,就需要考虑这些对象是否为同一个了。实际上只要来自同一个继承体系,就可能造成“别名”

条款12:复制对象时勿忘每一个成分

当你编写一个 copying 函数,请确保(1)复制所有的 local 成员变量 (2)调用所有 base classes 内的适当的 copying 函数

不应该令 copy assignment 操作符调用 copy 构造函数,反过来也一样。构造函数用来初始化新对象,而 assignment 操作符只施行于已初始化对象身上

条款13:以对象管理资源

为确保返回的资源总是被释放,我们需要将资源放进对象内,当控制流离开负责析构该资源的函数时,该对象的析构函数会自动释放那些资源

auto_ptr 是个“类指针(pointer-like)对象”也就是所谓的“智能指针”,其析构函数自动对所指对象调用 delete 

注意不要让多个 auto_ptrs 同时指向同一个对象。如果那样的话,对象会被删除一次以上,会导致未定义的错误行为

为了预防这个问题,auto_ptrs 有一个特别的性质--若通过 copy 构造函数或 copy assignment 操作符复制它们,它们就会变成 null,而复制所得的指针将取得资源的唯一拥有权

auto_ptr 和 tr1::shared_ptr 两者都在其析构函数内做 delete 而不是 delete[] 动作,那意味着在动态分配而得到的 array 身上使用它们是不合适的,但是这种行为还是可以通过编译

条款14:在资源管理类中小心 copying 行为

禁止复制    可以将copy设置为父类的私有函数

对底层资源祭出“引用计数法”

复制底部资源      进行深拷贝

转移底部资源的拥有权  拷贝之后删除被拷贝物

条款15:在资源管理类中提供对原始资源的访问

//使用智能指针如 auto_ptr 或 tr1::shared_ptr 保存 factory 函数如 createInvestment 的调用结果:
std::tr1::shared_ptr<Investment> pInv(createInvestment());
//假如希望以某个函数处理 Investment 对象,像这样:
int daysHeld(const Investment* pi)   //返回投资天数
int days = daysHeld(pInv);   //错误!需要的是一个Investment*指针,传给它的却是个类型为 
                             //tr1::shared_ptr<Investment> 的对象

条款16:成对使用 new 和 delete 时要采取相同形式

delete 最大的问题在于:即将被删除的内存之内有多少对象?这个问题的答案决定了有多少个析构函数必须被调用

如果调用 new 时使用 [ ] ,必须在对应调用 delete 时也使用 [ ].如果调用 new 时没有使用 [ ] ,那么也不该在对应调用 delete 时使用 [ ].

条款17:以独立语句将 newed 对象置入智能指针

processWidegt(std::tr1::shared_ptr<widget>(new Widget),priority());

虽然我们在此使用"对象资源管理式资源",上述调用却可能泄露资源

万一对 priority 的调用导致异常,在此情况下"new Widget" 返回的指针将会遗失,因为它尚未被置入 tr1:shared_ptr 内

条款18:让接口容易被正确使用,不易被误用

用户可能传错数字或者传入无效的数字

条款19:设计 class 犹如设计 type

  • 新type的对象应该如何被创建和销毁?
  • 对象的初始化和对象的赋值该有什么样的差别?
  • 新type 的对象如何被 pased by vlaue,意味着什么?
  • 什么是新 type 的“合法值”?
  • 你的新 type 需要配合某个继承图系吗?
  • 你的新 type 需要什么样的转换?
  • 什么样的操作符和函数对此新 type 而言是合理的?
  • 什么样的操作符和函数对此新 type 而言是合理的?
  • 什么样的标准函数应该驳回?
  • 谁该取用新 type 的成员?
  • 什么是新 type 的“未声明接口”
  • 你的新 type 有多么一般化?
  • 你真的需要一个新 type 吗?

条款20:宁以 pass-by-reference-to-const 替换 pass-by-value

pass-by-value 有时会不必要的多次调用构造函数和析构函数(类本身调用,类中的成员调用)费时费力,可以用 pass-by-reference-to-const 来替代

class Window{
public:
  ...
  std::string name() const;   //返回窗口名称
  virtual void display() const;    //显示窗口和其内容
};

class WindowWithScrollBars: public Window{
public:
  ...
  virtual void display() const;
};

//现在假设希望写一个函数打印窗口名称,然后显示该窗口。下面是错误示范:
void printNameAndDisplay(Window w)   //不正确,参数会被切割
{
  std::cout << w.name();
  w.display();
}

WindowWithScrolBars wwsb;
printNameAndDisplay(wwsb);

//当调用上述函数并交给它一个 windowWithScrollBars 对象时,参数w会被构造成一个window对象,
//因为它是passed by value,造成wwsb“之所以是个 WindowWithScrollBars对象”的
//所有特化信息会被切除,所以在函数内调用的总是 Window::display绝不会是 //WindowWithScrollBars::display

解决切割问题的方法,就是 by reference-to-const 的方式传递 w

void printNameAndDisplay(const Window& w)
{
  std::cout<<w.name();
  w.display();
}

现在传进来的窗口是什么类型,w就表现出哪种类型

references 往往以指针实现出来,因此 pass by reference 通常意味着真正传递的是指针。因此如果传递的对象是内置类型(例如 int),pass by value 往往比 pass by reference 效率高些

条款21:必须返回对象时,别妄想返回其 reference

周所周知,return 返回的是一个浅拷贝副本,返回一个对象是没有问题的,但如果返回一个引用,原对象被销毁之后,引用的指向也被销毁了,也就是引用指空,出错。

我们当然可以用 new 解决这个问题,但是当变量数目多的时候,程序员往往不知道怎么使用 delete

总结:虽然返回一个对象需要构造,析构等操作而产生一些代价,但是如果我们不想改变已有的值,就最好不要返回一个引用,而是支付这些代价。(这在时间上会多一点,但创建的对象会随运算符的结束而被销毁。这比“未定义行为(返回一个新建对象的引用)”,“资源泄漏”,“结果出错”要好得多了。)

条款22:将成员变量声明为 private

条款23:宁以 non-member,non-friend 替换 member 函数

条款24:若所有参数皆需类型转换,请为此采用 non-member 函数

class Rational
{
public:
    Rational(int numerator = 0, int denominator = 1)//分子与分母
    ...
    const Rational operator*(const Rational& right_number) const;
    ...
};
 
Rational oneEighth(1, 8);
Rational onehalf(1, 2);
Rational result1 = onehalf * oneEighth;
Rational result2 = onehalf * 2;
Rational result3 = 2 * onehalf;//error!
 

onehalf*2 相当于 onehaf.operator*(2)

首先创建了一个临时对象 const Rational temp(2);

再让两个 Rational 对象运算。

2*onehalf 是 2 调用了operator*。因为 2 是需要被转换的参数,而 2 的位置和 this(调用operator *) 对象的位置是一样的,所以无法将 2 转换成 Rational 类型,也就无法调用 operator* 函数。

解决办法:使用 non-member 函数,让左右参数的地位平等:

const Rational operator*(const Rational& left_number, const Rational& right_number)
{...}

条款25:考虑写出一个不抛异常的 swap 函数

周所周知,swap 可以交换两个数的值,标准库的 swap 函数是通过拷贝完成这种运算的。想想,如果是交换两个类对象的值,如果类中变量的个数很少,那么 swap 是有一定效率的,但如果变量个数很多呢?

你一定联想到了之前提过的,引用传递替换值传递。没错,交换两个类对象的地址就可以很有效率地完成大量变量的 swap 操作。不幸的是,标准库的 swap 并无交换对象地址的行为,所以我们需要自己写 swap 函数。

class person{...};
void my_swap(person& p1, person& p2)
{
    swap(p1.ptr, p2.ptr);
}

这个函数无法通过编译,因为类变量是 private,无法通过对象访问。所以要把它变成成员函数。

class person
{
public:
    void my_swap(person& p)
    {
        swap(this->ptr, p.ptr);
    }
    ...
};

如果你觉得 p1.my_swap(p2) 的调用形式太low了,你可以设计一个non-member 函数(如果是在同一个命名空间那就再好不过了),实现swap(p1, p2),这里不做演示。你还可以特化 std 里的 swap 函数:

namespace std
{
    template<>
    void swap<person> (person& p1, person& p2)
    {
        p1.my_swap(p2);
    }
}

C++允许对模板类进行偏特化,不允许对模板函数进行偏特化。

条款26:尽可能延后变量定义式的出现时间

  • 尽可能延后变量定义式的出现时间。这样可增加程序的清晰度并改善程序效率
  • 你不应该只延后变量的定义,指导非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止。
  • 如果一个变量只在循环内使用,那么把它定义于循环外并每次给他赋值比较好,还是把它定义于循环内较好呢?这个问题值得思考。
     

通过 default 构造函数构建一个对象然后对它赋值比直接在构造时指定初值效率差 

条款27:尽量少做转型动作

请记住:

  • 如果可以,尽量避免转型,特别是在注重效率的代码中使用dynamic_cast。如果有个设计需要转型动作,试着发展无需转型的替代设计。
  • 如果转型是必要的,试着将它隐藏域某个函数背后。客户随后可以调用该函数,而不需要将转型放进他们自己的代码中。
  • 宁可使用C++-style转型,不要使用旧式转型。前者很容易辨别出来,而且也比较有着分门别类的职掌。
     

1,旧式类型转换

(T) expression
T(expression)

2,新式类型转换

const_cast<T>(expression)
dynamic_cast<T>(expression)
reinterpret_cast<T>(expression)
static_cast<T>(expression)

3,const_cast通常被用来将对象的常量性转除。它也是唯一有此能力的C++-style转型操作符;reinterpret_cast意图执行低级转型,实际动作由编译器决定,这也就意味着它不可移植,很少使用;static_cast用来强迫隐式转换,一般用在内置类型的一些转换。

4,dynamic_cast主要用于“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型,它是唯一无法由旧式语法执行的动作。通常一个继承体系下,如果有虚函数,一般不用dynamic_cast。一般用在那种不能设置为虚函数的函数调用。dynamic_cast执行速度慢,是因为他会使用RTTI机制,使用type_id找类型,耗时。

virtual void onResize() {
	static_cast<Window>(*this).onResize();
}

这段代码,static_cast中传值方法是值传递,值传递肯定要一个copy的动作,所以会产生一个副本,所以,修改这个副本,不会影响this指针。

应该这样使用:

virtual void onResize() {
	Window::onResize();
}

条款28:避免返回 handles 指向对象内部成分

reference,指针,迭代器都是所谓的 handle ,返回一个代表对象内部数据的 handle 会降低对象封装性,还可能导致”虽然调用 const 成员函数却造成对象状态被更改“

请记住:

避免使用 handles(包括 references,指针,迭代器)指向对象内部。遵守这个条款可增加封装性,帮助 const 成员函数的行为像个 const ,并将发生”虚吊的号码牌“可能性降至最低

条款29:为“异常安全”而努力是值得的

当异常被抛出时,带有异常安全性的函数会:

  • 不泄露任何资源
  • 不允许数据败坏

异常安全函数(Exception-safe functions) 提供以下三个保证之一:

  • 基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。
  • 强烈保证:如果异常被抛出,程序状态不改变。调用这样的函数需要这样的认知:如果函数成功,就是完全成功,如果函数失败,程序会回复到“调用函数之前”的状态
  • 不抛掷保证,承诺绝不抛出异常。因为它们总是能够完成它们原先承诺的功能。

copy-and-swap:为你打算修改的对象做出一份副本,然后在副本身上进行一切必要修改,然后将修改后的数据和原件置换。

请记住:

  • 异常安全函数即使发生异常也不会泄露资源或者允许任何数据额结构破坏。这样的函数区分为三种可能得保证:基本型、强烈型、不抛异常型
  • “强烈保证”往往能够以copy-and-swap实现出来,但“强烈保证”并非对所有函数都可实现或具备现实意义
  • 函数提供的“异常安全保证”通常最高只等于其所调用之各个函数的“异常安全保证”中的最弱者,短板效应
     

条款30:透彻了解 inline 的里里外外

请记住;

  • 将大多数inline限制在小型、被频繁调用的函数身上。这可使得日后的调试过程和二进制升级更容易,也可使潜在代码膨胀问题最小化,使程序的速度提升机会最大化
  • 不要只因为function template出现在头文件,就将他声明为inline
  1. 编译器如果要对函数做inline,那么它必须知道inline函数长什么样子。这句话说明,inline得在头文件中,发生在编译期。
  2. 虚函数、构造、析构函数不适合inline。
  3. inline会引发的问题有:代码膨胀,修改inline导致全重编译。
  4. 记住中第二点说:不要只因为function template出现在头文件,就将他声明为inline。因为,template本身就会代码膨胀,inline也会导致这个问题,如果两个在一起,那就是膨胀+膨胀。
     

参考文章:EFFECTIVE C++ (万字详解)(一)-CSDN博客

《Effective C++》笔记_effectivec++ 笔记-CSDN博客

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

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

相关文章

基于ssm旅游景点管理系统设计论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本旅游景点管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

深度学习中的预测图片中的矩形框、标签、置信度分别是什么意思。

问题描述&#xff1a;深度学习中的预测图片中的矩形框、标签、置信度分别是什么意思。 问题解答&#xff1a; 目标框&#xff08;Bounding Box&#xff09;&#xff1a; 描述目标位置的矩形边界框。 类别标签&#xff1a; 表示模型认为目标属于哪个类别&#xff08;例如&#…

证明四元数乘法与旋转矩阵乘法等价

刚体四元数姿态控制 一文中没有证明的公式 R ( Q 1 ) R ( Q 2 ) R ( Q 1 ∘ Q 2 ) R(Q_1)R(Q_2)R(Q_1\circ Q_2) R(Q1​)R(Q2​)R(Q1​∘Q2​) 在这篇文章中证明。 首先找几个数测试是否等价。 quaternions.py的代码见 自用的四元数、欧拉角、旋转矩阵转换代码。 下面的代码中…

dockerfite创建镜像---INMP+wordpress

搭建dockerfile---lnmp 在192.168.10.201 使用 Docker 构建 LNMP 环境并运行 Wordpress 网站平台 [rootdocker1 opt]# mkdir nginx mysql php [rootdocker1 opt]# ls #分别拖入四个包&#xff1a; nginx-1.22.0.tar.gz mysql-boost-5.7.20.tar.gz php-7.1.10.tar.bz2 wor…

重要通知!中国电信警告:用户须关闭路由器“双频合一”功能

在网络的无尽时空里&#xff0c;一场电信官方的宣战正酝酿中&#xff0c;目标锁定在我们日常生活中不可或缺的WiFi身上~ 最新消息曝光&#xff0c;竟然是路由器内藏的一个名为“双频合一”的功能引发了这场轰轰烈烈的网络风暴。 我们时常觉得WiFi就像是隐身在我们生活中的超级英…

Faulhaber 2.5代运动控制系统 25mNm/13W

2.5代控制系统&#xff1b; PWM输出&#xff1b; 四象限控制带&#xff1b; RS232或CANopen通信接口&#xff1b; 2250_BX4_CxD 选件&#xff0c;电缆和连接信息&#xff1a; 适配部件&#xff1a;

SystemVerilog基础:并行块fork-join、join_any、join_none(二)

相关阅读 SystemVerilog基础https://blog.csdn.net/weixin_45791458/category_12517449.html 在第一节中&#xff0c;我们讨论了并行块中的fork-join块和fork-join_any块&#xff0c;了解了它们的差异&#xff0c;本文将继续讨论fork-join_none块的使用。 fork-join_none并行块…

Ubuntu 常用命令之 ll 命令用法介绍

ll是ls -l的别名&#xff0c;用于在Ubuntu系统中列出目录的详细信息。ls命令用于列出目录内容&#xff0c;-l选项则以长格式显示&#xff0c;包括文件类型、权限、链接数、所有者、组、大小、最后修改时间以及文件或目录名。 这是ll命令的基本格式 ll [选项]... [文件]...这是…

《地理信息系统原理》笔记/期末复习资料(9. 网络地理信息系统)

目录 9. 网络地理信息系统 9.1. 概述 9.1.1. 网络GIS概念 9.1.2. 网络GIS体系结构 9.1.3. 网络GIS内容体系 9.2. 分布式网络GIS 9.2.1. 分布式网络GIS概念 9.2.2. 分布式主要技术 9.3. WebGIS 9.3.1. WebGIS概念 9.3.2. WebGIS分类与特点 9.3.3. WebGIS技术框架 9…

Graphics Profiler 使用教程

GraphicsProfiler 使用教程 1.工具简介&#xff1a;2.Navigation介绍2.1.打开安装好的Graphics Profiler。2.2.将手机连接到计算机&#xff0c;软件会在手机中安装一个GraphicsProfiler应用(该应用是无界面的&#xff09;。2.3.Show files list2.4.Record new trace2.4.1.Appli…

Kotlin ArrayList类型toTypedArray转换Array

Kotlin ArrayList类型toTypedArray转换Array data class Point(val x: Float, val y: Float)fun array_test(points: ArrayList<Array<Point>>) {points.forEachIndexed { idx, ap ->ap.forEach {print("$idx $it ")}println()} }fun main(args: Arra…

第二届“奇安信”杯网络安全技能竞赛Reverse | pyre(需要用到反编译工具 pyinstxtractor.py)

赛题描述 这种exe文件怎么调用py的库&#xff1f; 题目附件&#xff1a;&#xff08;下载可能会有问题&#xff0c;记得直接跳过下载就可以了&#xff09; 抱歉无法处理您这个问题哦&#xff0c;您可以换个问题 PyInstaller Extractor 解包 适用场景 制作exe后丢失源代码 前…

基于中小微企业_个体工商户的信贷评分卡模型和用户画像(论文_专利_银行建模_企业调研)

背景介绍 信用贷款是指由银行或其他金融机构向中小微企业和个体工商户提供的一种贷款产品。该贷款的特点是无需提供抵押品或担保&#xff0c;主要依据借款人的信用状况来进行评估和审批。 中小微企业和个体工商户信用贷款的申请流程相对简单&#xff0c;申请人只需要提供个人…

Zebec 推出由 Visa、万事达网络支持的即时支付卡

“Zebec 现已推出全新的加密支付卡&#xff0c;该卡由 Visa、万事达网络支持&#xff0c;具备即时、多链、非托管、无需 KYC、免费等特性&#xff0c;其能够通过加密钱包与多条主流公链链接并直接调用支付&#xff0c;这将是加密支付领域的里程碑事件。” 在 2023 年的 12 月 8…

冗余备份组网——HSRP和GLBP协议

目录 HSRP&#xff08;思科私有协议&#xff09; HSRP基本概念 HSRP工作过程 HSRP的状态 HSRP的可靠性 HSRP相关配置 GLBP协议 HSRP&#xff08;思科私有协议&#xff09; HSRP基本概念 HSRP&#xff08;Host Standby Router Protocol&#xff09;为主机备份路由协议 …

B037-Mybatis基础

目录 为什么需要Mybatis&#xff1f;mybatis简介入门案例其余见代码查询流程增删改流程 - 变动数据要加事务去持久化抽取公共类 mapper接口开发规则概述代码 mapper.xml引入本地约束文件别名日志管理作用log4j的使用规范 井大括号与dollar大括号的区别 框架&#xff1a;半成品&…

C# OpenVINO 直接读取百度模型实现图片旋转角度检测

目录 效果 模型信息 代码 下载 C# OpenVINO 直接读取百度模型实现图片旋转角度检测 效果 模型信息 Inputs ------------------------- name&#xff1a;x tensor&#xff1a;F32[?, 3, 224, 224] --------------------------------------------------------------- Ou…

[RTOS移植]--STM32F767移植RTThread

文章目录 通过STM32cube创建一个工程选择要移植的RTOS源下载到本地如果没有重启软件选择对应配置后续补充 通过STM32cube创建一个工程 选择要移植的RTOS源 下载到本地 如果没有重启软件 选择对应配置 Build started: Project: STM32F767 *** Using Compiler V5.06 update 7 (b…

Self-Attention的学习

文章目录 Self-Attention模型的输入与输出1.为什么引入Self-Attention&#xff1f;2.Self-attention&#xff08;重点&#xff09;2.1 整体架构2.2 计算单个输出的原理2.3 整体的矩阵计算 3.Multi-head Self-attention4.Self-attention的缺点5.Self-attention与CNN的对比6.Self…

selenium 与 chromedriver安装

本文章向大家介绍selenium 安装与 chromedriver安装&#xff0c;主要包括selenium 安装与 chromedriver安装使用实例、应用技巧、基本知识点总结和需要注意事项供大家参考。 一、安装selenium 1、Selenium简介 Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开…