八股总结(一)C++语法、内存管理、新标准、STL

news2024/12/30 2:21:29

layout: post
title: 八股总结(一)C++语法、内存管理、新标准、STL
description: 八股总结(一)C++语法、内存管理、新标准、STL
tag: C++


文章目录

  • 基础语法
    • 语言特性
      • 面向对象的三大特性?
      • C++中新增了string,它与C语言中的char*有什么区别吗?它是如何实现的?
      • 如何用代码判断大小端存储
      • 网络字节序与主机字节序
      • C和C++的类型安全
        • 什么是类型安全?
        • C的类型安全
      • extern"C"的用法
    • 关键字
      • 重载(overload)、重写(override)、隐藏(hide)
      • override和final
      • volatile、mutable和explicit关键字用法
    • 宏定义与静态变量
      • 内联函数和宏定义的区别
      • 内联函数inline适用的场景
      • define宏定义和const的区别?
      • const和static的作用
    • 指针与引用
      • 一个指针占多少字节?
      • 指针与引用的区别与联系?
      • 在传递函数参数,如何决定是使用指针还是引用?
      • 顶层const与底层const的区别?
      • 数组名和指针(指向数组首元素的指针)的联系与区别?
      • 野指针和悬空指针定义、解决办法。
    • 类与模板
      • struct与class的区别?
      • C++有哪几种构造函数?
      • 成员初始化列表的概念,用它为什么会快一些?
      • public、protected和private访问权限和继承权限
  • 内存管理与拷贝控制
    • 内存安全管理
      • 内存分区
      • 堆与栈的区别
      • 什么是内存泄露,如何避免与检测
      • new / delete / 与malloc / free的异同
    • 拷贝控制
      • 浅拷贝和深拷贝的区别
      • 初始化和赋值的区别
      • 什么情况下会调用拷贝构造函数。
      • 说说移动构造函数
  • 异常处理
    • 常见错误类型
      • 写C++代码时有一类错误是 coredump ,很常见,你遇到过吗?怎么调试这个错误?

基础语法

语言特性

面向对象的三大特性?

  • 封装:将客观事物封装为抽象的类,并且类可以把自己的数据和方法只让可信的类或对象操作,对不信的进行信息隐藏。
  • 继承:使用现有类的所有功能,无需重写,直接对基类进行功能拓展延伸。
  • 多态:同一事物可以表现为不同事物的能力,不同对象在接收时产生不同的行为(重载实现编译时多态,虚函数实现运行时多态)。实现多态有两种方式:使用override(重写)和使用overload(重载)。

C++中新增了string,它与C语言中的char*有什么区别吗?它是如何实现的?

string继承自basic_string,其实是对char进行了封装,封装的string包含了char数组,容量、长度等属性。
string可以动态拓展,每次拓展时,另外申请了一块原空间两倍大小的空间,然后将原字符串拷贝过去,并加上新增的内容。

如何用代码判断大小端存储

大端存储:数据高位存在低地址中。
小端存储:数据低位存在低地址中。
unsigned int value = 0x12345678为例:
在小端模式下:随着地址增长,存放的是更高位的数据,因此高地址的0x12是数据的最高位数据。
在这里插入图片描述
使用代码判断大小端机器的方法:int整形强转为char型
由于int和char的长度不同,借助int型转换成char型,只会留下低地址的部分,低地址部分对应数据低位,说明是小端机器,否则为大端机器

#include <iostream>
using namespace std;
int main()
{
    int a = 0x1234;
    //由于int和char的长度不同,借助int型转换成char型,只会留下低地址的部分
    char c = (char)(a);
    if (c == 0x12)
        cout << "big endian" << endl;
    else if(c == 0x34)
        cout << "little endian" << endl;
}

网络字节序与主机字节序

主机字节序:就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。小端/大端的区别是指低位数据存储在内存低位还是高位的区别。其中小端机器指:数据低位存储在内存地址低位,高位数据则在内存地址高位;大端机器正好相反。

网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

所以: 在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是大端。由于 这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再 赋给socket。

C和C++的类型安全

什么是类型安全?

类型安全很大程度上可以等价于内存安全,类型安全的代码不会试图访问自己没被授权的内存区域。“类型安全”常被用来形容编程语言,其根据在于该门编程语言是否提供保障类型安全的机制;有的时候也用“类型安全”形容某个程序,判别的标准在于该程序是否隐含类型错误。

C的类型安全

C只在局部上下文中表现出类型安全,比如试图从一种结构体指针转为另一种结构体指针时,编译器将会报告错误,除非使用显式类型转换。然而C中相当多的操作是不安全的。以下是两个十分常见的例子:

  • printf格式输出
    在这里插入图片描述

  • malloc的函数返回值

malloc是C中进行内存分配的函数,它的返回类型是void*即空类型指针,常常有这样的用法char* pStr=(char*)malloc(100*sizeof(char)),这里明显做了显式的类型转换。

类型匹配尚且没有问题,但是一旦出现int* pInt=(int*)malloc(100*sizeof(char))就很可能带来一些问题,而这样的转换C并不会提示错误。

####C++的类型安全
如果C++使用得当,它将远比C更有类型安全,相对于C语言,C++提供了新的机制保障类型安全:

  • 操作new返回指针类型严格与对象匹配,而不是void*
  • C中很多void*为参数的函数可以改写为C++函数模板,而函数模板是支持类型检查的。
  • 引入了const关键字,代替#define constants,它是有类型,有作用域的,而#define constants只是简单的文本替换。
  • 一些#define宏,可以被改写为inline函数,结合函数的重载,可在类型安全的前提下支持多种类型,当然改写为模板也能保障类型安全。
  • C++提供了dynamic_cast关键字,使得转换过程更加安全,因为dynamic_cast比static_cast涉及更多具体的类型检查。

extern"C"的用法

为了能够正确的在C++代码中调用C语言的代码:在程序中加上extern "C"后,相当于告诉编译器这部分代码是C语言写的,因此要按照C语言进行编译,而不是C++;

哪些情况下使用extern “C”:

(1)C++代码中调用C语言代码;

(2)在C++中的头文件中使用;

(3)在多个人协同开发时,可能有人擅长C语言,而有人擅长C++;

关键字

重载(overload)、重写(override)、隐藏(hide)

  1. 重载(overload):在同一范围定义中的同名成员函数才存在重载关系。特点是函数名相同,参数类型和数目有所不同,不能出现参数个数和类型均相同,仅仅依靠返回值不同来区分的函数。重载和函数成员是否为虚函数无关。
  2. 重写(override):重写指的是在派生类中覆盖基类中的同名虚函数,重写就是重写函数体,要求基类函数必须是虚函数且与基类的虚函数有相同的参数个数、参数类型和返回值类型。

重载和重写的区别:

  • 重写是父类与子类之间的垂直关系,重载是同名不同参数的函数之间的水平关系。
  • 重写要求参数列表相同,重载则要求参数列表不同,返回值不同。
  • 重写关系中,调用方法根据对象类型决定,重载根据调用时实参与形参表的对应关系选择函数体。
  1. 隐藏(hide)
    隐藏指的是某些情况下,派生类中的函数屏蔽了基类中的同名函数,包含以下情况:
  • 两个函数参数相同,但是基类函数不是虚函数,和重写的区别在于基类函数是否为虚函数。
  • 两个函数参数不同,无论基类函数是否为虚函数,都会被隐藏,和重载的区别在于,两个函数不在同一个子类中。

override和final

当在父类中使用虚函数时,子类可以对这个函数进行重写。

class A
{
    virtual void foo();
}
class B : public A
{
    void foo(); //OK
    virtual void foo(); // OK
    void foo() override; //OK
}

使用override指定重写父类的虚函数,编译器可以帮助我们检查父类中是否有该虚函数。比如,假定我们将foo写成了f00,有override的话,编译器发现父类中没有该虚函数不会通过编译,而不加override,会被认定为子类的新的方法,造成错误。

当不希望某个类被继承、或者不希望某个虚函数被重写,可以在类名和虚函数后添加final关键字,添加final关键字后被继承或重写,编译器会报错。

volatile、mutable和explicit关键字用法

  1. volatile(易变的、不稳定的)关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其他线程。遇到volatile关键字,编译器对访问该变量的代码不再进行优化,从而可以提供对特殊地址的稳定访问。volatile定义变量的值是易变的,每次用到这个变量的值的时候都要去重新读取这个变量的值,而不是读寄存器内的备份。多线程中被几个任务共享的变量需要定义为volatile类型

volatile指针:volatile 指针和 const 修饰词类似,const 有常量指针和指针常量的说法,volatile 也有相应的概念
修饰由指针指向的对象、数据是 const 或 volatile 的:

const char* cpch;volatile char* vpch;

修饰指针自身的值——即地址本身是const或者volatile的:

char* const pchc;char* volatile pchv;

  1. mutable(可变的,易变的),C++中mutable是为了突破const的限制而设置的,被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数。

  2. explicit
    explicit(明确的)关键字用来修饰类的构造函数,被修饰构造函数的类,不能发生相应的隐式类型转换,只能以显式的方式进行类型转换。
    注意:

  • explicit关键字只能用于类内部的构造函数的声明
  • explicit关键字作用于单个参数的构造函数
  • 被explicit修饰的构造函数的类,不能发生相应的隐式类型转换。

宏定义与静态变量

内联函数和宏定义的区别

  • 在使用时:宏只做简单字符串替换,而内联函数可以进行参数类型检查且具有返回值。
  • 内联函数在编译时直接将函数代码嵌入到目标代码中,省去了函数调用时的开销,以提高执行效率,并且进行参数类型检查,有返回值,可以实现重载。
  • 宏定义时要注意书写(参数括起来),否则容易出现歧义,内联函数不会产生歧义。

内联函数inline适用的场景

  • 使用宏定义的地方都可以使用 inline 函数。
  • 作为类成员接口函数来读写类的私有成员或者保护成员,会提高效率。

define宏定义和const的区别?

  • 编译阶段上:
    define是在编译的预处理阶段起作用,而const是在编译、运行时候起作用。
  • 安全性上:
    define只做替换,不做类型检查和计算,也不求解,容易产生错误,一般最好加一个大括号包住全部的宏定义内容,不然容易出错,而const是常量是有数据类型的,编译器可以对它进行安全检查。
  • 内存占用上:
    define只是将宏名称进行替换,在内存中会产生多份相同的备份,const在程序运行中只有一份备份,且可以执行常量折叠,能将复杂的的表达式计算出结果放入常量表。

const和static的作用

static

  • 不考虑类的情况:

    • 隐藏的功能,不加static的全局变量和全局函数具有全局可见性,可以在其他文件中使用,加了static之后的全局变量和全局函数只能在该文件所在的编译模块中使用。
    • 默认初始化为0,存储在静态数据区,省去了置零的操作。
    • 保存数据内容的持久化,具备记忆性。在程序的执行路径第一次经过对象定义语句的时候初始化,并且直到程序终止才被销毁,期间的任务数据修改都具有持久记忆性。(不会因为退出函数等被销毁,除非再次被修改,否则直到程序结束前,值都是不变的)。
  • 考虑类的情况:

    • static静态成员函数和静态成员不与类对象绑定在一起,所有类对象的静态成员共享一份内存数据。不由类的构造函数初始化,因此必须在类的外部定义和初始化每个静态成员
    • static静态成员函数不具有this指针(因为不与类对象绑定,所有类对象共享访问),static成员函数内不可以访问非static成员变量和非static成员函数;不能被声明为const、虚函数和volatile.

const

  • 不考虑类的情况:
    • const常量在定义时必须初始化,初始化后不能修改。
    • const形参可以接收const和非const类型实参
  • 考虑类的情况:
    • const成员变量:不能在类定义外部初始化(与static静态成员变量相反),只能通过构造函数初始化成员列表进行初始化,并且必须有构造函数,不同类对象的const数据成员值可以不同,所以不能在类中声明时初始化。
    • const成员函数:const对象不可以调用非const成员函数,不可改变非mutable数据的值。

指针与引用

一个指针占多少字节?

64位的编译环境下,指针占用大小为8(8 ×8 = 64)个字节,在32位编译环境下,指针占用大小为 4 (4 ×8 = 32)个字节。

指针与引用的区别与联系?

  • 指针是一个变量,存储的是一个地址,引用是变量的别名,跟原变量是一个东西。
  • 指针可以有多级,即可以定义指针的指针,而引用则不能。
  • 指针可以为空,可以初始化为null,初始化后还可以改变指针的指向,而引用则必须在定义时初始化,一旦初始化绑定变量后,就不可再改变。
  • 指针与引用作为参数传递时,都可以改变实参的值,不同的是,指针作为参数传递时,是将指针的一个拷贝传递给形参,两者指向相同地址,但不是同一个变量,在函数中改变这个变量的指向,不会影响实参,但引用可以。
  • 引用的本质是一个指针常量(指针中的常量),指向不可改变。

在传递函数参数,如何决定是使用指针还是引用?

  • 需要返回函数内局部变量的内存的时候使用指针,指针传参需要开辟内存,用完需要释放指针,否则会内存泄露,而返回局部变量的引用是没有意义的。
  • 对栈空间大小敏感(比如递归)的时候使用引用,不需要创建临时变量,内存开销小。
  • 类对象作为参数传递的时候,使用引用,这是C++类对象传递的标准方式。

顶层const与底层const的区别?

  • 顶层const: *const,指针常量,指针中的常量,指向不可修改。
  • 底层const:const (int)✳, 常量指针,常量的指针,所指对象视为常量,不可改变所指对象。
int i =0;
int *const p1 = &i; // 顶层const,不可改变p1
const int ci = 42;
const int *p2 = &ci; // 允许改变p2,不可改变ci,这是底层const
const int *const p3 = p2; // 靠右的const是顶层const,靠左的const是底层const
const int &r = ci; // 用于声明引用的const都是底层const

当执行对象的拷贝操作时,顶层const和底层const区别明显。其中顶层const不受影响,底层const的限制不可忽视。一般来讲,非常量可以转为常量,而常量不可转为非常量。

i = ci;  // 正确
p2 = p3; // p2和p3所指对象类型相同,p3顶层const的部分不受影响。
int *p = p3; // 错误,p3包含底层const的含义,即所指对象不可修改,而p没有,如果这样定义,可能出现通过p修改常量的错误操作
p2 = p3; // 正确,p2和p3都是底层const
p2 = &i; // 正确,int * 可以转成 const int *
int &r = ci; // 错误,普通的int不可以绑定到int常量上,如果这样做,可能出现通过r修改常量ci的错误操作
const int &r2 = i; // 正确,const int & 可以绑定到一个普通的int上。

事实上底层const出现限制的原因主要在于由于底层const所指对象为常量,故绑定引用或者给指针赋值时,可能出现通过该引用或指针去修改常量的后果,出现这种后果的拷贝操作都是错误的

数组名和指针(指向数组首元素的指针)的联系与区别?

  • 二者均可以通过增减偏移量来访问数组中的元素。
  • 数组名不是真正意义上的指针,可以理解为常指针,所以数组名没有自增、自减操作。
  • 数组名当做形参传递给调用函数后,就失去了常指针的特性,退化为一般指针,可以自增、自减,且sizeof运算符不再能得到原数组的大小了。

野指针和悬空指针定义、解决办法。

  • 野指针:没有初始化的指针
int main(void) { 
    
    int* p;     // 未初始化
    std::cout<< *p << std::endl; // 未初始化就被使用
    
    return 0;
}

  • 悬空指针:指针最初指向的内存已经被释放的一种指针。
int main(void) { 
  int * p = nullptr;
  int* p2 = new int;
  
  p = p2;

  delete p2;
}

此时 p和p2就是悬空指针,指向的内存已经被释放。继续使用这两个指针,行为不可预料。需要设置为p=p2=nullptr。此时再使用,编译器会直接保错。 避免野指针比较简单,但悬空指针比较麻烦。c++引入了智能指针,C++智能指针的本质就是避免悬空指针的产生。

  • 产生原因和解决方法:
    野指针:指针变量未及时初始化 => 定义指针变量及时初始化,要么置空(= nullptr)。
    悬空指针:指针free或delete后没有及时置空 =>释放操作后立即置空。

类与模板

struct与class的区别?

  • 相同点
    • 两者都拥有成员函数、公有和私有部分
    • 任何可以使用class完成的工作,同样可以使用struct完成
  • 不同点
    • 两者中如果不对成员不指定公私有,struct默认是公有的,class则默认是私有的

    • class默认是private继承, 而struct默认是public继承
      成员类别上,struct默认成员为public,class默认成员为private;继承关系上,struct默认公有继承,private默认私有继承。

C++有哪几种构造函数?

  • 默认构造函数
  • 初始化构造函数(有参数)
  • 拷贝构造函数
  • 移动构造函数(move和右值引用)
  • 委托构造函数
  • 转换构造函数

成员初始化列表的概念,用它为什么会快一些?

在类的构造函数中,不在函数体内对成员变量赋值,而是 在花括号前边使用冒号和初始化列表赋值。

用它会快一些的原因是,对于有类成员的情况,它少了一次调用构造函数的过程,而在函数体中赋值则会多一次调用,(函数体中需要一次默认构造,加一次赋值,而初始化成员列表只做一次赋值操作),而对于内置数据类型成员则没有差异。

public、protected和private访问权限和继承权限

  • public成员类内和类外都可以访问,protected成员只能在类内或者派生类中访问,private的成员只能在类内访问。

在这里插入图片描述

内存管理与拷贝控制

内存安全管理

内存分区

C++程序在执行时,将供用户使用内存大致划分为四个区域:

(1)代码区:存放函数体的二进制代码,由操作系统进行管理;

(2)全局区:存放全局变量和静态(全局、局部)变量和字符串常量;

(3)栈区(stack):由编译器自动分配释放, 存放函数的参数值,局部变量等;

(4)堆区(heap):由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

堆与栈的区别

  • 申请方式不同:堆区是自行申请和释放,栈区是系统分配和释放。
  • 申请空间大小、排布、限制不同:栈区是一片连续的空间,大小由操作系统预定好,在Windows下是2M,空间较小,由高地址向低地址生长,如果申请空间大于剩余空间,分配失败,栈溢出。堆区在内存中是不连续的(系统使用链表存储空闲内存地址,自然是不连续的),堆大小受限于计算机系统中的有效虚拟内存(32位机理论上为4G),堆区较大。
  • 申请效率不同:栈有系统自动分配,申请效率高,堆由开发者申请,效率低,且容易产生内存碎片。

形象的比喻

栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。

堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

什么是内存泄露,如何避免与检测

内存泄露:
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定)内存块,使用完后必须显式释放的内存。应用程序般使用malloc,、realloc、 new等函数从堆中分配到块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了

避免内存泄露的几种方式:

  • 计数法:使用new或者malloc时,让该数加1,delete或free时,该数减1,程序执行完毕时打印这个数,如果不为0,表示存在内存泄露。
  • 一定要将基类中的析构函数声明为虚函数。
  • 对象数组的释放一定要使用delete[]
  • 有new就有delete,有malloc就有free,保证他们成对出现。

new / delete / 与malloc / free的异同

  • 相同点
    • 都可以用于内存的动态申请和释放
  • 不同点
    • 从定义上讲,new与delte是C++运算符,malloc和free是C++标准库函数,因此new与delete,不依赖外部库函数文件,malloc和free则需要依赖外部库函数文件。
    • 从使用上讲, new自动计算分配空间大小,malloc申请的空间大小需要手工计算; new是类型安全的,malloc不是。
    • 从执行过程上讲:
      new调用名为operator new的标准库函数,分配足够空间,并调用相关对象的构造函数,delete对指针所指对象运行对应的析构函数,然后通过调用名为operator delete的标准库函数释放该对象所用的内存。malloc与free均没有相关的调用。new 是封装了malloc,直接free不会报错,但只是释放内存,不会析构对象。
int *p = new float[2]; // 编译错误
int *p = (int*)malloc(2 * sizeof(double)); // 编译无错误

拷贝控制

浅拷贝和深拷贝的区别

  • 浅拷贝:浅拷贝只是拷贝一个指针,并没有开辟一个地址,拷贝的指针和原来的指针指向同一块的地址,如果原来的指针所指向的资源被释放了,那么再释放浅拷贝的指针的资源就会出现错误。
  • 深拷贝:深拷贝不仅拷贝值,还开辟了一块新的空间用于存放新的值,即使原先的对象被析构掉,释放内存了也不会影响到深拷贝的值,在自己实现拷贝赋值时,如果有指针成员变量,是需要自己实现深拷贝的。

初始化和赋值的区别

  • 对于简单类型而言,初始化和赋值没有区别。
  • 对于类和复杂数据类型(指针)而言,两者区别很大,类可能重载了赋值运算符。
class A{
public:
    int num1;
    int num2;
public:
    A(int a=0, int b=0):num1(a),num2(b){};
    A(const A& a){};
    //重载 = 号操作符函数
    A& operator=(const A& a){
        num1 = a.num1 + 1;
        num2 = a.num2 + 1;
        return *this;
    };
};
int main(){
    A a(1,1);
    A a1 = a; //拷贝初始化操作,调用拷贝构造函数
    A b;
    b = a;//赋值操作,对象a中,num1 = 1,num2 = 1;对象b中,num1 = 2,num2 = 2
    return 0;
}

什么情况下会调用拷贝构造函数。

  • 用类的一个实例化对象去初始化另一个对象时。
  • 函数的参数是类的对象时(非引用传递)
  • 函数的返回值是函数体局部对象的类时,返回值调用拷贝构造函数。

说说移动构造函数

  1. 移动构造函数设计的初衷:当我们用对象a初始化对象b后,对象a不再使用了,但是对象a的空间还在(没有析构),既然拷贝的目的是为了把a对象的内容复制一份给b,那么使用移动构造函数能够直接使用a的空间,避免新空间的分配,大大降低了构造成本。
  2. 拷贝构造函数中,对于指针我们一定要采用深拷贝,而移动构造函数中,对于指针,我们采用浅拷贝,浅拷贝之所以危险,是因为两个指针共同指向一片内存空间,若第一个指针将其释放,另一个指针的指向就不合法了。
  3. 移动构造函数的参数和拷贝构造函数不同,拷贝构造参数是一个左值引用,移动构造函数的参数是一个右值引用。

异常处理

常见错误类型

写C++代码时有一类错误是 coredump ,很常见,你遇到过吗?怎么调试这个错误?

coredump是程序由于异常或者bug在运行时异常退出或者终止,在一定的条件下生成的一个叫做core的文件,这个core文件会记录程序在运行时的内存,寄存器状态,内存指针和函数堆栈信息等等。对这个文件进行分析可以定位到程序异常的时候对应的堆栈调用信息。

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

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

相关文章

Acwing---843. n-皇后问题

n-皇后问题1.题目2.基本思想3.代码实现1.题目 n−皇后问题是指将 n 个皇后放在 nn 的国际象棋棋盘上&#xff0c;使得皇后不能相互攻击到&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上。 现在给定整数 n&#xff0c;请你输出所有的满足条件的棋子摆法。 …

数据库调优策略

1.数据库调优的措施 1.1.调优的目标 尽可能节省系统资源&#xff0c;以便系统可以提供更大负荷的服务。(吞吐量更大)合理的结构设计和参数调整&#xff0c;以提高用户操作 响应的速度。(响应速度更快)减少系统的瓶颈&#xff0c;提高MySQL数据库整体的性能 1.2.如何定位调优…

Qt 绘制图表 - Qt Charts版

一、前言 自从 Qt 发布以来&#xff0c;给广大跨平台界面研发人员带来了无数的福利。但是Qt自己却一直没有提供自带的图表库&#xff0c;这就使得 QWT、QCustomPlot 等第三方图表库有了巨大的生存空间&#xff0c;为了降低开发成本&#xff0c;大家都涌向了这些第三方库。这种…

appium的安装详解

安装appium 爬虫手机APP需要实现自动化&#xff0c;所以要使用appnium来实现点击&#xff0c;输入&#xff0c;滑动等操作。由于appnium的安装较为繁琐&#xff0c;所以特意整理一篇文章来展示安装的详细过程过程中。 安装appnium共有3个步骤 安装 Android SDK安装 JDK安装 …

W800系列|ST-LINK|STM32最小版|HEX文件|CKLINK|DebugServer|学习(3):自制cklink调试工具

硬件准备 1.stm32最小系统板&#xff1a;stm32c8t6 2.stlink下载器&#xff1a;stlink v2版本 软件安装&#xff1a; 1、STM32 ST-LINK Utility&#xff08;官网下载&#xff09; 2、csky IDE: 剑池CDK集成开发环境V2.18.2 https://occ.t-head.cn/community/download?id…

链接投票二维码制作制作投票链接视频选举投票制作

关于微信投票&#xff0c;我们现在用的最多的就是小程序投票&#xff0c;今天的网络投票&#xff0c;在这里会教大家如何用“活动星投票”小程序来进行投票。我们现在要以“信赖挚友”为主题进行一次投票活动&#xff0c;我们可以在在微信小程序搜索&#xff0c;“活动星投票”…

activiti整合springBoot其他操作

如果单纯使用activiti进行流程的自动控制&#xff0c;是可以实现的。但是通常我们都需要结合自定义的表&#xff0c;便于在流程执行中更加清晰的看到每一个流程实例节点的具体信息。关联自定义表与activiti表才能完成真正的业务 BusinessKey关联 // 定义businessKey Test pub…

【UML+OOPC嵌入式C语言开发】使用C语言实现一个面向对象语言才能够实现的类

文章目录简述OOPC开发环境知识讲解函数示例类的实现示例接口实现示例&#xff08;前面两部分有点无聊&#xff0c;如果大家没兴趣看可以直接从知识讲解开始看&#xff09; 简述OOPC oopc&#xff0c;是一种轻量级的面向对象的C语言编程框架&#xff0c; LW_OOPC是Light-Weight …

学习C++这几个网站足矣

文章目录cppreferencecplusplusquick-bench[C 之父的网站](https://www.stroustrup.com/bs_faq.html)C提案[Cpp Core Guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)[C Super-FAQ](https://isocpp.org/faq)[learn c](https://www.learncpp.com/)[A…

从上海分时电价机制调整看转供电用户电能计费

安科瑞 耿敏花2022年12月16日&#xff0c;上海市发改委发布《关于进一步完善我市分时电价机制有关事项的通知》(沪发改价管〔2022〕50号)。通知明确上海分时电价机制&#xff0c;一般工商业及其他两部制、大工业两部制用电夏季&#xff08;7、8、9月&#xff09;和冬季&#xf…

Codeforces Round 855 (Div. 3)(A~F)

A. Is It a Cat?定义满足条件的字符串为&#xff1a;其中仅可能含有meow四种字母的大小写&#xff0c;而且相同种类的字母必须挨在一起&#xff0c;四种字母的顺序必须按照meow排列。给出一个字母串&#xff0c;求是否满足条件。思路&#xff1a;感觉是个很麻烦的模拟。首先把…

这6个高清图片素材库,马住,马住~

网上找的图片素材清晰度不够&#xff0c;版权不明确怎么办。看看这几个可商用图片素材网站&#xff0c;解决你的所有图片需求&#xff0c;高清无水印&#xff0c;赶紧马住&#xff01; 1、菜鸟图库 美女图片|手机壁纸|风景图片大全|高清图片素材下载网 - 菜鸟图库 ​ 网站素材…

Vector - CAPL - 简介及数据结构

对于想进入车载行业或者已经在车载行业工作的朋友对于CAPL这个词都会相当的熟悉&#xff0c;都知道他是做车载网络测试脚本的语言&#xff0c;并且跟C有点类似&#xff0c;但是它到底是什么呢&#xff1f;CAPL全称&#xff08;Communication Access Programming Language&#…

Qt 崩溃 corrupted double-linked list Aborted

文章目录摘要1 使用全局静态变量2 不取第一个和最后一个数3 将数据计算放到同一线程计算4 替换槽函数5 修改传值为const6 神奇的环境因素7 更神奇的板子差异8 另一个细节Aborted最后关键字&#xff1a; Qt、 Aborted、 corrupted、 double、 linked 摘要 额&#xff0c;结论&…

【上位机入门常见问题】SQLServer2019 安装指导

SQLServer2019 安装指导 这里要说一下SQLServer的版本问题&#xff0c;首先说纵向的高低版本&#xff0c;如果大家跟我学习&#xff0c;我教给大家的是T-SQL编程的方法&#xff0c;而不是直接操作菜单的方法&#xff0c;所以&#xff0c;我们学习中只要使用SQLServer2012或以上…

嵌入式学习笔记——STM32单片机开发前的准备

STM32单片机开发前的准备1.集成开发环境的选取STM32 CubeIDEKEIL_MDK2.KEIL_MDK环境搭建安装包获取及安装芯片包下载及安装工程建立(STM32F407VET6为例)1.新建工程文件夹2.新建工程3.安装ST-LINK以及CH340的驱动4.设置KEIL&#xff0c;并烧录本文重点1.集成开发环境的选取 前面…

深入分析Vert.x里Future的compose() 和 map()

Vert.x 是一个异步框架。因此&#xff0c;它需要一种方法来表示可能尚未准备好但将来可用的值&#xff0c;也称为延迟值(deferred values)。您可能熟悉不同名称的延迟值&#xff1a;Promise, Future, Deferred, Mono, Uni 都是延迟值设计模式的实现。 Vert.x 有自己的延迟值实…

IP 地址类型有哪些?

IP 地址有不同的类别&#xff0c;每个类别内有不同的类型。消费者 IP 地址具有互联网服务计划的每个个人或企业都将拥有两种类型的 IP 地址&#xff1a;专用 IP 地址和公共 IP 地址。术语“公共”和“专用”与网络位置有关 - 即&#xff0c;在网络内部使用专用 IP 地址&#xf…

【C++】30h速成C++从入门到精通(内存管理、函数/类模板)

C内存分布我们先来看一下下面的一段代码相关问题int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char* pChar3 "abcd";int* ptr1 (int*)mal…

离线数据仓库项目搭建——准备篇

文章目录&#xff08;一&#xff09;什么是数据仓库&#xff08;二&#xff09;数据仓库基础知识&#xff08;三&#xff09;数据仓库建模方式&#xff08;1&#xff09;星行模型&#xff08;2&#xff09;雪花模型&#xff08;3&#xff09;星型模型 VS 雪花模型&#xff08;四…