[c++] c++ 中的顺序(构造,析构,初始化列表,继承)

news2024/11/17 15:49:28

对象构造的时候,对象成员变量的初始化顺序是什么样的 ?

派生类构造的时候,先构造基类还是先构造派生类 ?

构造函数中的初始化列表,初始化的顺序是列表的顺序吗 ?

析构的时候,析构的顺序是什么样的 ?

本文通过实例代码记录上述场景下的顺序。先说结论:

(1)全局对象以及静态全局对象,在 main 函数调用之前创建

(2)构造时,先构造类中的成员变量,再调用构造函数

(3)类中成员变量的构造顺序是变量在类中声明的顺序

(4)初始化列表中,成员变量的初始化顺序也是变量在类中声明的顺序

(5)对于派生类来说,先构造基类,再构造派生类

(6)对于多重继承的场景,基类构造的顺序是继承列表的顺序

(7)多重继承中如果有虚拟继承,那么先构造虚拟基类

(8)析构的顺序与构造的顺序是相反的

1 静态变量在 main 函数调用之前创建

main 函数是我们应用中第一个执行的函数,但却不是系统加载应用时第一个调用的函数。在 main 函数正式运行前,最基础的这个应用的环境变量如果需要配置则要进行配置;应用入参如果有需要也应该把入参放到规定的位置;对于全局变量和静态全局变量,也是在 main 函数初始化之前构造的。

#include <iostream>
#include <string>
#include <unistd.h>

class Test1 {
public:
  Test1() {
    std::cout << "Test1()" << std::endl;
  }

  ~Test1() {
    std::cout << "~Test1()" << std::endl;
  }
};

class Test2 {
public:
  Test2() {
    std::cout << "Test2()" << std::endl;
  }

  ~Test2() {
    std::cout << "~Test2()" << std::endl;
  }

private:
  static Test1 t1;
};

Test1 Test2::t1;

Test1 t1;
static Test2 t2;

void Do() {
  std::cout << "Do()" << std::endl;
  static Test1 t1;
}

int main() {
  std::cout << "main" << std::endl;
  sleep(2);
  static Test1 t1;
  Do();
  Do();
  return 0;
}

运行结果如下,从结果中还可以看出,对于局部静态变量来说,是在函数第一次调用的时候构造的。这也体现了懒加载的思想,局部静态变量在第一次函数调用之前,根本就没有用,直接构造这个对象是浪费时间和内存资源。

 
使用 gdb 对 Test1 的构造函数设置断点,可以看到 Test1 的调用栈。

2 构造顺序和析构顺序

对于一个没有继承其它类的类来说,构造顺序有以下几点:

(1)构造的时候先构造类的成员变量,再调用构造函数。这也可以理解,符合我们的使用习惯,因为构造函数中可以使用这个对象中的成员变量,所以调用构造函数的时候,成员变量需要初始化好。

(2)成员变量的构造顺序(也叫初始化顺序)是变量在类中声明的顺序。可以猜测,编译器编译的时候是直接按顺序解析类中的成员变量,然后按这个顺序进行初始化的。这样也符合我们的使用习惯,在使用变量的时候,后声明的变量,可能会使用到之前声明的变量,所以从上向下进行初始化。

(3)成员变量的构造顺序和变量的权限是没有关系的,只有一个影响因素,那就是变量在类中的声明顺序。

静态成员是属于类的,不是属于对象的。

静态成员变量在进程中只有一份,被所有对象所共享。

静态成员在程序启动的时候就会创建,而不是在构造对象的时候再创建。

析构顺序,是构造顺序的逆:

(1)先调用析构函数,再析构类中的成员变量

(2)成员变量的析构顺序与变量在类中声明的顺序是相反的

如下是验证代码,代码中有 3 个类 Test1 ~ Test3。另外有 3 个类 Test4 ~ Test5,这 3 个类中有 3 个成员变量,分别是 Test1 ~ Test3,这 3 个变量的声明顺序是不一样的,访问权限也是不一样的。通过这个代码可以观察构造顺序和析构顺序。

#include <iostream>
#include <string>

class Test1 {
public:
  Test1() {
    std::cout << "Test1()" << std::endl;
  }

  ~Test1() {
    std::cout << "~Test1()" << std::endl;
  }
};

class Test2 {
public:
  Test2() {
    std::cout << "Test2()" << std::endl;
  }

  ~Test2() {
    std::cout << "~Test2()" << std::endl;
  }
};

class Test3 {
public:
  Test3() {
    std::cout << "Test3()" << std::endl;
  }

  ~Test3() {
    std::cout << "~Test3()" << std::endl;
  }
};


class Test4 {
public:
  Test4() {
    std::cout << "Test4()" << std::endl;
  }

  ~Test4() {
    std::cout << "~Test4()" << std::endl;
  }

  Test1 test1;
  Test2 test2;
  Test3 test3;
};

class Test5 {
public:
  Test5() {
    std::cout << "Test5()" << std::endl;
  }

  ~Test5() {
    std::cout << "~Test5()" << std::endl;
  }

  Test3 test3;
  Test2 test2;
  Test1 test1;
};

class Test6 {
public:
  Test6() {
    std::cout << "Test6()" << std::endl;
  }

  ~Test6() {
    std::cout << "~Test6()" << std::endl;
  }

private:
  Test3 test3;
  Test2 test2;

public:
  Test1 test1;
};


int main() {
  std::cout << "t4 --------" << std::endl;
  Test4 t4;
  std::cout << "t5 --------" << std::endl;
  Test5 t5;
  std::cout << "t6 --------" << std::endl;
  Test6 t6;
  std::cout << "----------------" << std::endl;
  return 0;
}

运行结果如下:

如下代码,运行结果如下,从运行结果也可以看出来,在调用构造函数的时候,打印 a_ 是 10,这说明在调用构造函数的时候,成员变量已经完成了初始化。

#include <iostream>
#include <string>

class Test {
public:
  Test() {
    std::cout << "Test(), a_ = " << a_ << std::endl;
    a_ = 100;
    std::cout << "a_ = " << a_ << std::endl;
  }

  ~Test() {
    std::cout << "~Test()" << std::endl;
  }

  int a_ = 10;
};

int main() {
  Test t;
  return 0;
}

3 初始化列表

3.1 初始化列表初始化顺序

初始化列表的初始化顺序有以下几点需要注意:

(1)初始化列表中变量初始化的顺序,不是按照列表的顺序,仍然是按照成员变量在类中声明的顺序。

(2)初始化列表中的初始化也是在调用构造函数之前完成。

(3)如果类中的成员变量有的在初始化列表中进行初始化,有的不在初始化列表中进行初始化,整体的初始化顺序仍然是按照变量在类中声明的顺序。

(4)初始化列表中初始化的变量,不会重复初始化。也就是说不会在初始化列表初始化之前初始化一次,到初始化列表中再初始化一次。

如下代码中 Test3 初始化列表中的顺序和变量在类中声明的顺序不一样,变量的构造顺序仍然按照变量在类中声明的顺序初始化;Test5 中,初始化列表中只初始化了 test1,test1 和没有放到初始化列表中的 test2 和 tes3 的相对顺序仍然是它们在类中声明的顺序。

#include <iostream>
#include <string>

class Test1 {
public:
  Test1() {
    std::cout << "Test1()" << std::endl;
  }

  ~Test1() {
    std::cout << "~Test1()" << std::endl;
  }
};

class Test2 {
public:
  Test2() {
    std::cout << "Test2()" << std::endl;
  }

  ~Test2() {
    std::cout << "~Test2()" << std::endl;
  }
};

class Test3 {
public:
  Test3() {
    std::cout << "Test3()" << std::endl;
  }

  ~Test3() {
    std::cout << "~Test3()" << std::endl;
  }
};


class Test4 {
public:
  Test4() : test3(), test1(), test2() {
    std::cout << "Test4()" << std::endl;
  }

  ~Test4() {
    std::cout << "~Test4()" << std::endl;
  }

  Test1 test1;
  Test2 test2;
  Test3 test3;
};

class Test5 {
public:
  Test5() : test1() {
    std::cout << "Test5()" << std::endl;
  }

  ~Test5() {
    std::cout << "~Test5()" << std::endl;
  }

  Test3 test3;
  Test2 test2;
  Test1 test1;
};

class Test6 {
public:
  Test6() : test1(), test2(), test3() {
    std::cout << "Test6()" << std::endl;
  }

  ~Test6() {
    std::cout << "~Test6()" << std::endl;
  }

private:
  Test3 test3;
  Test2 test2;

public:
  Test1 test1;
};


int main() {
  std::cout << "t4 --------" << std::endl;
  Test4 t4;
  std::cout << "t5 --------" << std::endl;
  Test5 t5;
  std::cout << "t6 --------" << std::endl;
  Test6 t6;
  std::cout << "----------------" << std::endl;
  return 0;
}

运行结果如下:

如下代码,两个成员变量 i 和 j,先声明的 i 后声明的 j,所以初始化顺序是先 i 后 j。在初始化列表中对 i 进行初始化的时候,j 还没有初始化,所以 i 是一个随机值,j 是 10。

#include <iostream>
#include <string>

class Test {
public:
  Test(int a) : j(a), i(j) {
    std::cout << "Test(), j = " << j << ", i = " << i << std::endl;
  }

  ~Test() {
    std::cout << "~Test()" << std::endl;
  }

  void Print() {
    std::cout << "Print(), j = " << j << ", i = " << i << std::endl;
  }

private:
  int i;
  int j;
};


int main() {
  std::cout << "main" << std::endl;
  Test t(10);
  t.Print();
  return 0;
}

 运行结果如下:

3.2 const 变量和引用只能在初始化列表中初始化

(1)const 常量和引用必须在初始化列表中进行初始化,不能在构造函数中初始化

(2)const 常量只能在初始化列表中初始化,构造函数和其它地方不能修改

(3)引用在初始化列表中初始化之后,在其它地方也可以进行修改

#include <iostream>
#include <string>

class Test {
public:
  Test(int a, int &b) : a_(a), b_(b) {
    std::cout << "Test(), a = " << a_ << ", b = " << b_ << std::endl;
    // a_ = a; 编译错误
    b_ = b;
  }

  ~Test() {
    std::cout << "~Test()" << std::endl;
  }

  void Print() {
    std::cout << "Print(), a = " << a_ << ", b = " << b_ << std::endl;
  }

private:
  const int a_;
  int &b_;
};

int main() {
  int a = 10;
  int b = 20;
  Test t(a, b);
  t.Print();
  return 0;
};

3.3 基类构造只能在初始化列表中初始化

#include <iostream>
#include <string>

class Base {
public:
  Base(int a, int b) : a_(a), b_(b) {
    std::cout << "Base(), a = " << a_ << ", b = " << b_ << std::endl;
  }

  ~Base() {
    std::cout << "~Base()" << std::endl;
  }

  void Print() {
    std::cout << "Print(), a = " << a_ << ", b_ = " << b_ << std::endl;
  }

public:
  int a_;

private:
  int b_;
};


class Derived : public Base {
public:
  Derived(int data) : Base(data, data * 2), data_(data) {
    // 这句,语法没有错,但是不能起到初始化基类的作用
    // 只是生成了一个基类的临时对象
    // 初始化基类只能在初始化列表中
    Base(data * 10, data * 20);
    std::cout << "Derived()" << std::endl;
  };

  ~Derived() {
    std::cout << "~Derived()" << std::endl;
  }

private:
  int data_;
};

int main() {
  Derived d(10);
  d.Print();
  return 0;
}

4 继承

当派生类构造的时候,先构造基类,再构造派生类。这也是符合常识的,派生类是继承基类而来,没有构造出基类对象,何来派生类对象,派生类对象从哪继承。

4.1 单继承

如下代码,Derived 继承了 Base,构造 Derived 的时候,先构造 Base 再构造 Derived。

#include <iostream>
#include <string>
#include <unistd.h>

class Base {
public:
  Base() {
    std::cout << "Base()" << std::endl;
  }

  ~Base() {
    std::cout << "~Base()" << std::endl;
  }
};

class Derived : public Base {
public:
  Derived() {
    std::cout << "Derived()" << std::endl;
  }

  ~Derived() {
    std::cout << "~Derived()" << std::endl;
  }
};

int main() {
  std::cout << "main" << std::endl;
  Derived d;
  return 0;
}

4.2 多继承

多重继承是一个类可以继承多个类。多重继承意思是一个类需要同时具备多个类的属性,从现实语义上来说,多重继承更像是组合的语义。多继承的语法和语义,让人感觉有点别扭,与常识也是不大符合的,但是 c++ 中支持这种语法。

4.2.1 构造顺序

(1)基类构造的顺序按继承列表的顺序进行构造,而不是按照初始化列表中声明的顺序进行构造

(2)如果有虚拟继承,那么先构造虚拟继承的基类

#include <iostream>
#include <string>
#include <unistd.h>

class Base1 {
public:
  Base1(int a) : a_(a) {
    std::cout << "Base1() a = " << a_ << std::endl;
  }

  ~Base1() {
    std::cout << "~Base1()" << std::endl;
  }

  int a_;
};

class Base2 {
public:
  Base2(int a) : a_(a) {
    std::cout << "Base2() a = " << a_ << std::endl;
  }

  ~Base2() {
    std::cout << "~Base2()" << std::endl;
  }

  int a_;
};

class Base3 {
public:
  Base3(int a) : a_(a) {
    std::cout << "Base3() a = " << a_ << std::endl;
  }

  ~Base3() {
    std::cout << "~Base3()" << std::endl;
  }

  virtual void Do3() {
    std::cout << "Do3, a = " << a_ << std::endl;
  }

  int a_;
};

class Base4 {
public:
  Base4(int a) : a_(a) {
    std::cout << "Base4() a = " << a_ << std::endl;
  }

  ~Base4() {
    std::cout << "~Base4()" << std::endl;
  }

  virtual void Do4() {
    std::cout << "Do4, a = " << a_ << std::endl;
  }

  int a_;
};

class Derived1 : public Base1, public Base2 {
public:
  Derived1() : Base2(20), Base1(10) {
    std::cout << "Derived1()" << std::endl;
  }

  ~Derived1() {
    std::cout << "~Derived1()" << std::endl;
  }
};

class Derived2 : public Base1, public Base2 {
public:
  Derived2() : Base1(100), Base2(200) {
    std::cout << "Derived2()" << std::endl;
  }

  ~Derived2() {
    std::cout << "~Derived2()" << std::endl;
  }
};

class Derived3 : public Base3, public Base4 {
public:
  Derived3() : Base4(400), Base3(30) {
    std::cout << "Derived3()" << std::endl;
  }

  ~Derived3() {
    std::cout << "~Derived3()" << std::endl;
  }
};

class Derived4 : public Base1, public Base4, public Base3, virtual public Base2 {
public:
  Derived4() : Base1(1000), Base2(2000), Base3(3000), Base4(4000) {
    std::cout << "Derived4()" << std::endl;
  }

  ~Derived4() {
    std::cout << "~Derived4()" << std::endl;
  }
};


int main() {
  std::cout << "main" << std::endl;
  std::cout << "d1 --------" << std::endl;
  Derived1 d1;
  std::cout << "d2 --------" << std::endl;
  Derived2 d2;
  std::cout << "d3 --------" << std::endl;
  Derived3 d3;
  std::cout << "d4 --------" << std::endl;
  Derived4 d4;
  return 0;
}

运行结果如下:

(1)Derived1 和 Derived2 都是多继承 Base1 和 Base2,继承列表中顺序是一致的,初始化列表中是不一样的。基类构造顺序都是继承列表的顺序。

(2)Derived4 虚拟继承了 Base2,并且 Base2 在继承声明的最后,构造 Derived4 的时候也是先构造 Base2。

4.2.2 多重继承的二义性以及怎么避免

如下代码,两个基类,Base1 和 Base2,两个基类有两个相同的函数 Speak()。Derived1 类继承自 Base1 和 Base2,当通过 Derived1 对象调用 Speak 的时候,会产生二义性。编译不知道调用的这个 Speak 是 Base1 中的还是 Base2 中的。

消除二义性,可以通过在调用的时候指定是哪个基类中的方法。

#include <iostream>
#include <string>


class Base1 {
public:
  Base1() {
    std::cout << "Base1()" << std::endl;
  }

  ~Base1() {
    std::cout << "~Base1()" << std::endl;
  }

  void Speak(std::string str) {
    std::cout << "Base1 speak: " << str << std::endl;
  }
};

class Base2 {
public:
  Base2() {
    std::cout << "Base2()" << std::endl;
  }

  ~Base2() {
    std::cout << "~Base2()" << std::endl;
  }

  void Speak(std::string str) {
    std::cout << "Base2 speak: " << str << std::endl;
  }
};


class Derived1 : public Base1, public Base2 {
public:
  Derived1() {
    std::cout << "Derived1()" << std::endl;
  }

  ~Derived1() {
    std::cout << "Derived1()" << std::endl;
  }
};

int main() {
  Derived1 d1;
  // d1.Speak(); // 二义性
  d1.Base1::Speak("hello");
  return 0;
}

如下图所示,Derived1 和 Derived2 继承自 Base1,Derived3 继承自 Derived1 和 Derived2。这样当 Derived3 调用 Speak() 的时候就会产生二义性,因为 Speak 在 Derived1 和 Derived2 中各有一份。

有两种方法可以消除这个代码中的二义性,个人更倾向于使用第一种,这样语法清晰。

(1)代码中指定使用哪个类中的函数

d3.Derived1::Speak("hello");

(2)将 Derived1 和 Derived2 改成虚拟继承

#include <iostream>
#include <string>


class Base1 {
public:
  Base1() {
    std::cout << "Base1()" << std::endl;
  }

  ~Base1() {
    std::cout << "~Base1()" << std::endl;
  }

  void Speak(std::string str) {
    std::cout << "Base1 speak: " << str << std::endl;
  }
};

class Derived1 : virtual public Base1 {
public:
  Derived1() {
    std::cout << "Derived1()" << std::endl;
  }

  ~Derived1() {
    std::cout << "Derived1()" << std::endl;
  }
};

class Derived2 : virtual public Base1 {
public:
  Derived2() {
    std::cout << "Derived2()" << std::endl;
  }

  ~Derived2() {
    std::cout << "Derived2()" << std::endl;
  }
};

class Derived3 : public Derived1, public Derived2 {
public:
  Derived3() {
    std::cout << "Derived3()" << std::endl;
  }

  ~Derived3() {
    std::cout << "Derived3()" << std::endl;
  }
};


int main() {
  Derived3 d3;
  d3.Speak("hello"); // 二义性
  return 0;
}

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

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

相关文章

华为数通方向HCIP-DataCom H12-821题库(多选题:41-60)

第41题 BGP OPEN消息中携带如下哪些信息? A、路由属性 B、BGP Router ID C、Hold time D、本地自治系统(AS)号 【参考答案】BCD 【答案解析】 B. BGP Router ID:OPEN消息中包含发送方BGP路由器的Router ID,用于唯一标识BGP路由器。C.Hold time:OPEN消息中包含发送方BGP路由…

区块链媒体发布推广10个热门案例解析-华媒舍

区块链技术的发展已经引起了媒体的广泛关注&#xff0c;越来越多的区块链媒体纷纷发布推广相关的热门案例。本文将介绍10个成功的区块链媒体推广案例&#xff0c;并分享它们的成功秘诀&#xff0c;帮助读者更好地了解区块链媒体推广的方法与技巧。 随着区块链技术的成熟和应用场…

vue2本地开发环境正常,生产环境下this.$router.push({ name: ‘login‘ })不跳转

如果在Vue.js 2中在本地开发环境下正常运行,但在生产环境下使用​​this.$router.push({ name: login })​​不起作用,可能有几个原因需要检查和解决: 路由配置问题: 确保你的路由配置正确,特别是确保在生产环境中,路由的配置和本地开发环境一致。检查是否正确设置了name…

课程表系列(BFS)

广度优先搜索 文章目录 广度优先搜索207. 课程表210. 课程表 II思路 630. 课程表 III1462. 课程表 IV547. 省份数量 207. 课程表 207. 课程表 你这个学期必须选修 numCourses 门课程&#xff0c;记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程…

多元函数积分思路合集

[曲线积分笔记]第一类曲线积分 [微积分笔记]第二类曲线/面积分总结 积分方法意义/提示平面第二型曲线积分化为定积分 ∮ L → ∫ a b \oint_L \to \int_a^b ∮L​→∫ab​平面第二型曲线积分格林公式 ∮ L → ∬ D \oint_L \to \iint_D ∮L​→∬D​化为对平面区域的二重积分空…

百度搜索引擎SEO优化方法

随着互联网的不断发展&#xff0c;搜索引擎已经成为人们获取信息、产品和服务的主要途径之一。而在中国&#xff0c;百度作为最大的搜索引擎&#xff0c;其影响力不可忽视。了解并掌握百度SEO关键词优化方法&#xff0c;对于提升网站在搜索引擎中的排名至关重要。 关键词选择&a…

chatgpt-3的文章生成器有哪些?可以批量生成文章的生成器

GPT-3&#xff08;Generative Pre-trained Transformer 3&#xff09;作为人工智能领域的一项重大突破&#xff0c;开启了新一代的文本生成技术。同时市面上也涌现出了一些GPT-3文章生成器&#xff0c;为用户提供了快速、高效地生成各种类型文章的工具。本文将介绍一些中国的GP…

JS:原型与原型链(附带图解与代码)

一、原型 写在前面&#xff1a; 任何对象都有原型。 函数也是对象&#xff0c;所以函数也有原型。 1.什么是原型 在 JavaScript 中&#xff0c;对象有一个特殊的隐藏属性 [[Prototype]]&#xff0c;它要么为 null&#xff0c;要么就是对另一个对象的引用&#xff0c;该对象…

MATLAB基于隐马尔可夫模型-高斯混合模型-期望最大化的MR图像分割

隐马尔可夫模型是一种统计模型&#xff0c;它描述了马尔可夫过程&#xff0c;隐马尔可夫过程中包含隐变量&#xff0c;语音识别和词性自动标注等一些领域常常使用隐马尔可夫模型方法来处理。马尔可夫过程是一类随机过程&#xff0c;马尔可夫链是它的原始模型&#xff0c;马尔可…

《OpenScene: 3D Scene Understanding with Open Vocabularies》阅读笔记1

传统的3D场景理解方法依赖于带标签的3D数据集,用于训练一个模型以进行单一任务的监督学习。我们提出了OpenScene,一种替代方法,其中模型在CLIP特征空间中预测与文本和图像像素共同嵌入的3D场景点的密集特征。这种零样本方法实现了与任务无关的训练和开放词汇查询。例如,为了…

03-JNI 类型和数据结构

上一篇&#xff1a; 02-设计概述 本章讨论 JNI 如何将 Java 类型映射为本地 C 类型。 3.1 原始类型 下表描述了 Java 原始类型及其与机器相关的本地等价类型。 为方便起见&#xff0c;定义如下&#xff1a; #define JNI_FALSE 0 #define JNI_TRUE 1 jsize 整数类型用于描述…

《Spring Security 简易速速上手小册》第8章 常见问题与解决方案(2024 最新版)

文章目录 8.1 异常处理和日志记录8.1.1 基础知识详解8.1.2 重点案例&#xff1a;统一异常处理案例 Demo拓展 8.1.3 拓展案例 1&#xff1a;日志记录策略案例 Demo拓展 8.1.4 拓展案例 2&#xff1a;日志聚合案例 Demo拓展 8.2 多租户安全性问题8.2.1 基础知识详解8.2.2 重点案例…

Redis之十:Spring Data Redis --- CrudRepository方式

SpringData Redis CrudRepository方式 Spring Data Redis 的 CrudRepository 是 Spring Data 框架中用于提供基础 CRUD&#xff08;创建、读取、更新和删除&#xff09;操作的一个接口。在与 Redis 集成时&#xff0c;尽管 Redis 是一个键值存储系统&#xff0c;并没有像关系型…

STM32使用FlyMcu串口下载程序与STLink Utility下载程序

文章目录 前言软件链接一、FlyMcu串口下载程序原理优化手动修改跳线帽选项字节其他功能 二、STLink Utility下载程序下载程序选项字节固件更新 前言 本文主要讲解使用FlyMcu配合USART串口为STM32下载程序、使用STLink Utility配合STLink为STM32下载程序&#xff0c;以及这两个…

javascript中对包含关系判断介绍

本文将为您详细讲解 JavaScript 中对包含关系的判断&#xff0c;包括数组、字符串等&#xff0c;并提供相应的代码例子。 1. 数组包含关系判断 在 JavaScript 中&#xff0c;数组包含关系判断通常使用 Array.prototype.includes() 方法。这个方法返回一个布尔值&#xff0c;表示…

C语言第三十四弹---动态内存管理(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 动态内存管理 1、动态内存经典笔试题分析 1.1、题目1 1.2、题目2 1.3、题目3 1.4、题目4 2、柔性数组 2.1、柔性数组的特点 2.2、柔性数组的使用 2.3、…

7、Bluecms代码审计

一、sql注入 环境 流程:将bluecms文件夹放到WWW中,访问文件中的install(安装文件)&#xff0c;安装后可以删掉成功后直接访问bluecms目录即可后台访问报错解决。在php.ini配置文件里找到。关闭后记得重启phpstudy display_errors off建议删除安装文件或者将文件名更改1、sql…

【javaSE-语法】lambda表达式

【javaSE-语法】lambda表达式 1. 先回忆一下&#xff1a;1.1 接口不能直接通过关键字new进行实例化1.2 函数式接口1.3 匿名内部类1.31 匿名内部类在代码中长啥样&#xff1f;1.32 构造一个新的对象与构造一个扩展了某类的匿名内部类的对象&#xff0c;两者有什么区别&#xff1…

Bert基础(五)--解码器(下)

1、 多头注意力层 下图展示了Transformer模型中的编码器和解码器。我们可以看到&#xff0c;每个解码器中的多头注意力层都有两个输入&#xff1a;一个来自带掩码的多头注意力层&#xff0c;另一个是编码器输出的特征值。 让我们用R来表示编码器输出的特征值&#xff0c;用M来…

visio、ppt、office等另存图片,如何设置更清晰

visio、ppt、office等另存图片&#xff0c;如何设置更清晰 选中要另存为的部分——文件——另存为——选好位置——格式选jpg——保存——按下图设置&#xff1a;质量100%&#xff0c;分辨率选打印机&#xff0c;大小选屏幕——确定