c++ primer plus笔记 第十八章 探讨c++新标准

news2024/11/18 21:40:38

复习前面的内容:
1.auto,可以自动识别auto本身在这种语境下是什么类型

2.decltype,让一个变量的类型和另外一个变量的类型相同

decltype(x) y;//让y的类型和x的类型相同

如何理解?

decltype是一个关键词,其作用是检查括号内的表达式,并返回该表达式的类型,因此相当于用返回表达式的类型定义了y。

使用decltype的时候,需要注意的是:
 

int i;
decltype(i) j;//此时j是int类型
decltype((i)) j;//此时j的int&类型
//原因是在i外面再加一圈括号则会被看作为一个表达式,返回的类型将是内括号类型的引用

当定义一个模板函数的时候,有时候没办法确定返回的类型,比如说传入的一个是int类型,一个是double类型的时候返回的是double类型,如果传入的是两个int类型的时候,返回是int类型,为了解决这种情况,则可以使用decltype,

template<class T, class U>
auto sum(T &n, U m)->decltype(n+m)
{
    return n+m;
}

函数执行的顺序是,先传入参数,然后执行decltype关键词,auto根据decltype返回的类型来决定自己的类型。

3.回顾模板类中的隐式实例化,显示实例化,全部具体化,部分具体化

template<class T>;
template<typename T>;
//这两个模板头是一个意思,只是习惯问题,有些人喜欢用class,有些人喜欢用typename

1)隐式实例化,就像我们平时实例化一个模板类,用模板类创造一个对象就是在使用隐式实例化

template<class T>
class A
{
};
int main(void)
{

    A<int > a;//隐式实例化
    return 0;
}

2)显示实例化,不需要创造对象即可定义模板

template<class T>
class A
{
};
template class A<int >;//显示实例化, 不需要定义对象,但却实例化了模板类
int main(void)
{

    return 0;
}

3)全部具体化

具体化就是将类型参数限制住,使得模板类更加具体,当传入的类型参数为限制的类型的时候,使用的即为这个更具体的模板类的声明。

template <typename T, typename U>
class MyClass {
    //...
};
template <>//<>括号内填入不进行具体化的类型参数,全具体化没有不进行具体化的参数
class MyClass<int, double> {//对类型参数具体化
    // 这是一个全具体化版本
    // 当T和U分别为int和double时,会使用这个版本
    //...
};

4)部分具体化

template <typename T, typename U>
class MyClass {
    //...
};

template <typename T>//类型参数T不进行具体化,不进行具体化的类型参数要放进<>中
class MyClass<T, int> {
    // 这是一个部分具体化版本
    // 当U是int类型时,会使用这个版本
};

4.转换函数与单参数的构造函数的隐式转换问题

转换函数是将对象转换成其他类型,如

//定义一个转换函数,将复数对象转换成其实部
class Complex
{
private:
    double real;     // 实部
    double imaginary; // 虚部
 
public:
    // 构造函数
    Complex(double real = 0.0, double imaginary = 0.0) 
        : real(real), imaginary(imaginary)
    { }
 
    // 定义一个转换函数,将Complex对象转换为double
    operator double() const//转换函数不需要返回类型
    {
       return real; // 返回Complex对象的实部
    }
};

我们不希望以下的事情发生:
 

double a;
Complex temp;
a = temp;//这会隐式地将temp对象转换成double类型的数据,这可能不是我们想要发生生的
//则应该在转换函数前面加上explicit来禁止隐式转换,只允许显示转化
a = temp.operator double();//显示调用转换函数

但参数的构造函数可能也会发生类型的情况

比方说:
 

class A
{
    private:
        int num;
    public:
        A(int n = 0) : num(n) {}
}

int main(void)
{
    A temp1(10);
    temp1 = 20;//这将会用20作为参数隐式调用构造函数来创建一个无名对象,然后赋值给temp1;
    return 0;
}

我们不希望这样的事情发生,同样的,可以在这个单参数的构造函数前面加上explicit

5.

基于范围的for

c++11引入了基于范围的for,使得遍历容器或者数组变得更加方便,对于一般的数组:
 

int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for(int i : arr)
    cout << i << endl;
vector<int> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for(auto i : arr)
    cout << i << endl;
//将容器或者数组中的元素放到i中

6.

复习左值,右值,以及左值引用右值引用(第八章第9节)

一般来说,左值就是可以放在等号左边的值,右值就是可以放到等号右边的值,我们有一个技巧可以判断哪个是左值哪个是右值,一般来说,左值可以用&取地址,右值不可能用&取地址。而右值引用可以修改引用所指向的对象,右值引用一般用于移动语句。

什么叫做常引用?
常引用可以指向右值

const int &temp = (a+b);
//这将会在内存中创建一个临时变量来存放a+b,temp将是这个临时变量的别名
//但常引用无法改变该临时变量的值,只能读取

什么是右值引用?

int &&temp = (a+b);//定义一个右值引用

7.

作用域内枚举

当一个类中定义了两个枚举变量,但是这两个枚举变量中有相同的枚举量,我们可以使用类来将枚举量进行封装,然后用作用域来解决这个问题枚举量冲突问题,即在类的作用域中不会出现命名冲突。

class A
{
    public:
        enum class color1{Red,Blue, Green};
        enum class color2{Red, Yellow};//定义两个枚举类,用枚举类来封装枚举量
};
//这样就可以用类名加上作用域解析运算符来指定使用哪个枚举量


A::color1 c1 = A::color1::Red;
A::color2 c2 = A::color2::Red;

if (c1 == A::color1::Red) {
    // do something
}

if (c2 == A::color2::Red) {
    // do something else
}

8.

using=和typedef有什么区别?

c++11中可以使用using加别称 = 模板类名来给模板类起一个别名,而typedef无法做到,毕竟模板类是c++新增的东西。

如:
 

using v = std::vector<int>;
//让v和std::vector<int>等价,即v成为了别名

移动语义和右值引用

移动语义是什么意思?

移动语义是一种理念或方案,它通过避免昂贵的复制操作来提高性能,将右值引用所指向的内存好好利用,使用更改内存所有权的方式来实现复制而不是通过重新开辟内存的方式来复制。而移动构造函数和移动赋值运算符则是实现这种理念的工具或手段。

什么是移动构造函数和移动赋值运算符?

移动构造函数的参数是右值引用,移动构造函数的作用就是将右值引用所指向的对象的内存空间让给移动构造函数所要生成的对象,只是将一个对象的资源转让给另一个对象,相当于把这片内存改了个名字,原来是右值引用所指向的对象拥有的内存,变成了调用移动构造函数的对象的内存,并没有开辟新的内存。

移动赋值运算符也是同理,将右值引用所指向的对象所拥有的内存空间转让给了其他对象,也没有开辟新的内存。

什么时候调用移动构造函数?

当一个临时的对象(或称之为右值)给另一个对象进行初始化的时候,编译器将调用移动构造函数而非复制构造函数,这也是与复制构造函数的区别。

下面是一个使用移动构造函数和移动赋值运算符的例子,帮助理解:

#include <iostream>
#include <vector>

class MyClass {
private:
    int* data;

public:
    MyClass(int size) { // 构造函数
        data = new int[size];
        std::cout << "Constructor called!" << std::endl;
    }

    ~MyClass() { // 析构函数
        delete[] data;
        std::cout << "Destructor called!" << std::endl;
    }

    MyClass(const MyClass& other) = delete; // 禁止复制

    MyClass(MyClass&& other) noexcept : // 移动构造函数,noexcept保证函数不抛出异常,如果抛出异常将会直接终止程序
        data(other.data)
    {
        other.data = nullptr;
        std::cout << "Move constructor called!" << std::endl;
    }

    MyClass& operator=(MyClass&& other) noexcept { // 移动赋值运算符
        if(this != &other) {
            delete[] data; // 删除当前对象的资源
            data = other.data; // 赋值,将资源转让给调用构造函数的对象
            other.data = nullptr; // 置空
            std::cout << "Move assignment operator called!" << std::endl;
        }
        return *this;
    }
};

int main() {
    std::vector<MyClass> vec;

    vec.push_back(MyClass(50)); // push_back会调用移动构造函数

    MyClass a(100); // 正常构造
    MyClass b(200); // 正常构造

    b = std::move(a); // 调用移动赋值运算符

    return 0;
}

使用头文件utility中声明的函数std::move可以将对象的类型强制转换成右值引用,注意,记得将右值引用所指向的对象中使用了动态开辟内存的指针置空,否则该对象调用析构函数的时候将会回收这个已经让出去的内存空间。

编译器会自动生成那6个特殊的成员函数?
1. 默认构造函数

2. 默认析构函数

3.  默认复制构造函数

4.  默认赋值运算符

5. 移动构造函数

6. 移动赋值运算符

一旦你定义了移动构造函数或者移动赋值运算符,编译器将不再自动生成默认构造函数,默认复制构造函数,默认赋值运算符,因为编译器会认为你会完全管理资源,因此不再自动生成这些特殊的成员函数,反之,如果用户定义了构造函数,复制构造函数,以及赋值运算符中任意一个,都不会再自动生成移动构造函数,移动赋值运算符。

        需要注意的是复制构造函数和移动构造函数的参数是不同的,移动构造函数传入的不仅仅是右值引用,而且是没有const的,而复制构造函数带有const,原因是移动构造函数会更改传入的临时对象(或者右值)的指针,让其指向的内存转让给其他对象,然后自己指向空指针,这样才能完成空间的转让。

在上述情况下,如果仍然想让编译器自动生成相应的构造函数,可以在声明构造函数的后面加上default

如:
 

class MyClass
{
    
public:
    MyClass(MyClass &&mc);//一般来说定义了移动构造函数后,程序将不会自动生成复制构造函数
    MyClass(const MyClass &mc) = default;//显示得让程序生成复制构造函数
}

与default相对应得关键词是delete,使用delete可以禁止编译器使用特定的方法,即禁止某个函数的使用。

class MyClass
{
    
public:
    MyClass(MyClass &&mc);
    MyClass(const MyClass &mc) = delete;//禁止使用复制构造函数
}

什么是继承构造函数?

继承构造函数即为派生类构造函数直接继承基类的构造函数。

一般来说,构造函数,析构函数,赋值运算符,取地址运算符以及私有成员函数是派生了无法继承的,如果像继承基类的构造函数,则可以使用using来让派生类继承基类的所有构造函数,使用这种方法一般是因为基类的构造函数比较完整,用基类的构造函数就可以完成初始化,这样就可以省去重新定义一个和基类构造函数干相同事情的操作,即使用基类的构造函数却可以创造一个派生类的对象,我们一般说的构造函数无法继承的意思是说无法用基类的构造函数直接创建一个派生类的对象。

举个例子:

// 基类
class Base {
public:
    Base(int val) : value(val) {
        cout << "Base constructor called with value: " << value << endl;
    }

private:
    int value;
};

// 派生类
class Derived : public Base {
public:
    using Base::Base; // 使用基类的构造函数(继承构造函数)
};

int main() {
    Derived d(10); // 直接调用基类的构造函数
    return 0;
}
//派生类没有自己的成员变量,只有基类的构造函数即可完成初始化,使用继承构造函数就不需要自己定义构造函数了
//如果没有使用继承构造函数则需要定义一个调用基类构造函数的派生类构造函数
//Derived(int val) : Base(val) {} 

重新定义将隐藏方法是什么意思?
        意思就是说派生类如果定义了一个和基类方法同名的方法(不考虑参数,只考虑名字),这时候编译器将会只使用派生类的该方法而继承而来的同名方法将会被隐藏(覆盖),这样的现象就叫做"重新定义将隐藏方法"。

如果我像重新定义一个同名方法但却不想隐藏基类的方法应该怎么办?

class Derived : public Base
{
public:
    using Base::foo; // Unhide Base::foo(int x)
    void foo()
    {
        // ...
    }
//这个时候派生类中将有两个foo方法,一个是继承而来的基类方法foo,一个是自定义的foo
};

使用using既可将继承而来的基类方法显现而不会隐藏,这个时候就会根据参数的类型来调用不同版本的foo,传入int类型的参数就调用基类的方法,无参数就调用派生类的同名方法。

重载和重写以及重新定义有什么区别?

1.重载是在一个作用域内进行的,多定义几个参数列表(参数类型和参数个数以及返回值)不同但同名方法,这种叫做重载。重载通常发生在一个类内。

如:
 

   class Demo {
       void func() { ... }
       void func(int a) { ... }
       void func(double a, int b) { ... }
   }

2.

重写指的是派生类重写基类的方法,更改方法的行为,需要注意的是重写基类的方法要求派生类的方法必须与基类的方法具有完全相同的方法名以及参数列表,这时候如果通过派生类对象调用派生类方法的时候将会调用派生类的方法而不是基类的方法。

 3.

重新定义,我们知道重新定义将隐藏方法,在派生类重新定义方法有点像重载,但是重载一般发生在一个类中而且不要求像重写一样参数列表和函数名都相同,而这里的重新定义发生在派生类中,此时派生类将隐藏基类的同名方法,而只使用派生类重新定义的同名方法。

        这就是这三种的区别。

介绍两个关键词override和final

override用于派生类重写基类的方法,记住是重写,重写要求方法名和参数列表都必须相同,使用override是为了检查派生类重写格式是否有误。

final

final有两个作用,一是阻止类的进一步继承。二是阻止方法的进一步重写,但是重新定义是可以通过编译的。

如:

#include <iostream>
using namespace std;
class MyClass 
{
	public:
		virtual void fuc() final{cout << "Base " << endl;}
};

class Derive : public MyClass
{
	public:	
		void fuc() {cout << "Derive" << endl;}
		
};

int main(void)
{
	return 0;
}

这样编译是不会通过的,你这样相当于重写,派生类将基类的方法重写了。

但是重新定义是没有问题的

#include <iostream>
using namespace std;
class MyClass 
{
	public:
		virtual void fuc() final{cout << "Base " << endl;}
};

class Derive : public MyClass
{
	public:	
		void fuc(int n) {cout << "Derive" << endl;}
		
};

int main(void)
{
	Derive temp;
	temp.fuc(10);
	return 0;
}

重新定义将隐藏方法,即基类的方法将会被隐藏
 

Lambda函数

先回顾和介绍三种表达式for_each,count_if, generate

for_each(, ,)

第一个和第二个参数都是迭代器,第三个参数是要执行的操作,可以是函数指针,函数符或者是lambda函数,该表达式的作用就是遍历容器,执行操作。

count_if(,,)

第一个参数和第二个参数都是迭代器,第三个参数是要执行的操作,可以是函数指针,函数符或者是lambda函数,返回值要为bool类型,如果是true则计数+1,如果是false则计数-1,整个表达式的返回值是个整数,即计数值。

generate(,,)

第一个参数和第二个参数都是迭代器,第一个参数和第二个参数都是迭代器,第三个参数是要执行的操作,可以是函数指针,函数符或者是lambda函数,返回值要为容器所容纳的数据类型,该表达式的作用是填充容器的值;

#include <cstdlib>
#include <ctime>
#include <vector>
#incldue <algorithm>

//generate的使用:
srand(time(0));//产生随机数种子
int SIZE = 10;
vector<int > v(SIZE);
generate(v.begin(), v.end(), rand);//用随机数来填充vector

//count_if的使用:
bool countNum(int n)
{
    return n % 3 == 0;
}
int count = count_if(v.begin(), v.end(), countNum);

//for_each的使用:

void Show(int n)
{
    cout << n << endl;
}
for_each(v.begin(), v.end(), Show);

那什么是lambda函数呢?

lambda函数也叫做匿名函数,可以认为lambda函数就是一个小的函数,它是用来简化代码的一种方式。

形如:
 

[](int n)
{
    return n % 3 == 0;
}

lambda函数不用定义返回类型,其返回类型是使用decltype来决定的,也无需定义函数名。

[]是捕获列表,lambda函数可以访问作用域内的任何动态变量,而捕获列表指定(限制)了lambda函数可以访问所在作用域的那些变量和如何访问。

以下是一些常用的捕获方式:

  1. []:不捕获任何变量。

  2. [x][=]:按值捕获,创建x的一个新副本(不论x是值类型还是引用类型都只复制对象的值)。

  3. [&x][&]:按引用捕获,创建x的一个引用,可以改变x的值。

  4. [this]:捕获当前类的this指针,用于在lambda中访问类的成员。

  5. [x, &y]:混合捕获,可以同时捕获一些变量的副本和一些变量的引用

例子:

#include <iostream>
int main()
{
    int val = 1;
    auto copy_val = [val] { return val; };
    val = 100;
    auto stored_val = copy_val();
    std::cout << "stored_val: " << stored_val << std::endl; // 输出: stored_val: 1
    std::cout << "val: " << val << std::endl; //输出: val: 100

    int val_ref = 1;
    auto copy_ref = [&val_ref] { return val_ref; };
    val_ref = 100;
    auto stored_val_ref = copy_ref();
    std::cout << "stored_val_ref: " << stored_val_ref << std::endl; // 输出: stored_val_ref: 100
    std::cout << "val_ref: " << val_ref << std::endl; //输出: val_ref: 100
    return 0;
}

lambda函数也是可以有名字的,当lambda函数多次出现的时候,应该给lambda一个名字,简化代码,而不是用一次就定义一次,举个例子:

auto Add = [](int x, int y) {return x+y;}
//让lamb函数的名字确定为Add
int num = Add(5, 3);

包装器

包装器头文件functional下的一个模板类,可以用来优化程序,包装器可以接收函数,函数指针,函数对象以及lambda函数作为参数来初始化。

那么包装器有什么用呢?
用来优化程序,提高资源的利用率,比如说让模板类的实例化次数降低。

怎么做到的?

先看代码,下面解释。

#include <functional>
function<double(double) > ef = fuc;
//包装器ef可以接收一个参数是double且返回值为double的函数,函数指针,函数对象或者lambda函数
template<class T, class U>
T Fuction(T t, U u)
{
    return U(t);
};
//用包装器作为模板函数的参数,这样模板函数只会被实例化一次,因为我们传入的是包装器



        如果T的类型为double,函数,函数指针,函数对象,lambda函数作为参数U传入到模板类中,因为其类型不一样,所以U的类型的类型也不一样,导致模板类被实例化了4次。
但实际上可以使用一种方法来让模板类的实例化变为1次,那就是将特征标(参数列表和返回类型)相同的函数,函数指针,函数对象,以及lambda函数都封装成一种类型,这样U就是传入这种封装的类型,而不是分别传这4种类型,这样模板类就只会被实例化一次,第一个参数类型是double,而第二个参数类型是包装器。

        所以包装器就是一种封装手段,将特征标相同的函数,函数指针,函数对象以及lambda函数都看作为一种类型。

可变参数模板

可变参数模板是c++11推出的一种模板类,该模板类不限制类型参数的个数

下面是如何使用可变参数模板:

template<class T>//函数参数包中只剩一个参数的时候调用该模板函数,进行结束操作
void Show_List(T t)
{
    cout << t << endl;
}

template<class T, class...Args>//模板参数包,里面包的是传入的参数类型
void Show_List(T t, Args...args)//函数参数包,里面包的是传入的值
{
    cout << t << " ";
    Show_List(args...);//使用递归的方式来使用模板参数包里面的内容,相当于出栈,出栈后对栈剩下的部分再进行一次函数调用,直到只剩一个的时候再进行结束操作;

}

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

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

相关文章

【教程】APP备案全攻略:确保你的应用合规上线

【教程】APP备案全攻略&#xff1a;确保你的应用合规上线 摘要 本文详细介绍了中国大陆地区互联网信息服务提供者&#xff08;AP&#xff09;进行APP备案的流程、要求和注意事项。包括备案对象、备案方式、备案内容、备案流程等方面的详细说明&#xff0c;帮助开发者顺利完成…

微软模拟飞行器回放功能

参考b站up主&#xff0c;欢迎大家去关注&#xff1a;https://www.bilibili.com/video/BV1Z34y1P7zz/?spm_id_from333.880.my_history.page.click&vd_source4e0b40493e2382633fab2ddc1bb1d9cc 下载网址&#xff1a;https://flightsim.to/file/8163/flight-recorder 坠毁检…

微信公众号调用沙箱支付

沙箱支付 登录支付宝开放平台&#xff0c;选择底部沙箱支付 下载密钥生成工具 生成应用私钥与公钥&#xff0c;上传沙箱支付&#xff0c;获得支付宝公钥 配置支付通知与支付回调地址 SpringBoot配置 yml文件 这里的地址必须与沙箱配置的一样 controller package com.zq…

如何利用Python进行自动化测试和性能测试

在Python中&#xff0c;我们可以使用多种库和工具来执行自动化测试和性能测试。下面是一些示例代码&#xff0c;用于展示如何使用Python进行这两种类型的测试。 自动化测试 自动化测试通常使用诸如unittest或pytest这样的Python测试框架来执行。下面是一个使用unittest进行自…

RK3568驱动指南|第十三篇 输入子系统-第139章 输入子系统数据结构介绍

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

做抖音小店需要交钱吗?有门槛吗?都有哪些入驻条件和费用?

大家好&#xff0c;我是电商花花。 在抖音上开店已经成为很多人追逐的方向&#xff0c;因为这些人都看到别人在抖音上赚到钱&#xff0c;然后也想在抖音上尝试一下。 然而&#xff0c;许多人心中仍然存着一个问题&#xff0c;就是做抖音小店需要交钱吗&#xff1f;是否存在门…

长期异地就医备案有效期是多久?答记者问!

4、长期异地就医登记的有效期是多长&#xff1f; 答&#xff1a;异地长期就医登记长期有效。 如果您因个人原因需要变更长期居住地&#xff0c;只需提供相应的登记信息即可申请变更。 5、临时异地就医登记的有效期是多长时间&#xff1f; 答&#xff1a;临时异地就医登记包括…

《ElementPlus 与 ElementUI 差异集合》el-form-item CSS 属性 display 有变化

差异 element-ui el-form 中&#xff0c;属性display: flex; 导致元素在一排&#xff1b;element-plus el-form 中&#xff0c;属性display: block; 元素按照自己的属性排列&#xff1b; /* element ui */ display: block;/*element plus */ display: flex;如图所示 解决方案…

web基础05-jQuery

目录 一、jQuery 1.概述 2.原生js与jQuery对比 3.特点 4.使用 &#xff08;1&#xff09;入口函数 &#xff08;2&#xff09;语法 &#xff08;3&#xff09;jQuery选择器 5.方法 &#xff08;1&#xff09;获取属性值&#xff1a; &#xff08;2&#xff09;删除属…

在手机上欣赏无人直播,享受美好时光!

在这个充满着快节奏、高压力的现代社会中&#xff0c;人们经常感到身心疲惫&#xff0c;渴望找到一些放松和享受美好时光的方式。而随着科技的不断发展&#xff0c;手机已经成为人们生活中必不可缺的工具之一&#xff0c;为我们带来了诸多便利。其中&#xff0c;无人直播就是一…

MS5583N高分辨率模数转换器

产品简述 MS5583N 是一款高分辨率模数转换器&#xff0c;内部集 成高阶 Σ-Δ 调制器、低噪声可编程增益放大器、多 路输入选择器和多种内部数字滤波器。其转换速率 从 250SPS 到 4kSPS 。此外&#xff0c;芯片内部集成失调校准 寄存器和增益校准寄存器。 MS5583N …

精品基于Springboot的聊天交友系统的设计与实现

《[含文档PPT源码等]精品基于Springboot的聊天交友系统的设计与实现[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&#xf…

2023年中国高校大数据挑战赛D题参考论文发布(全网首发)

腾讯文档】2023年大数据挑战赛资料说明 https://docs.qq.com/doc/DSEpWUVFySm1ObFB0 基于数据分析的行业职业技术培训能力评价 摘要 中国是制造业大国&#xff0c;产业门类齐全&#xff0c;每年需要培养大量的技能娴熟的技术工人进入工厂。本文将基于题目给出的数据&#x…

力扣--动态规划5.最长回文子串

class Solution { public:string longestPalindrome(string s) {// 获取输入字符串的长度int n s.size();// 如果字符串长度为1&#xff0c;直接返回原字符串&#xff0c;因为任何单个字符都是回文串if (n 1)return s;// 创建一个二维数组dp&#xff0c;用于记录子串是否为回…

AI生成对抗网络的解释

了解生成对抗网络 &#xff08;GAN&#xff09; 的不同方面和复杂性&#xff0c;GAN 是一种在人工智能 &#xff08;AI&#xff09; 领域内外使用的神经网络。本文将向您介绍 GAN&#xff0c;介绍什么是 GAN&#xff0c;并解释如何使用它们。 GAN简介 今天对称为 GAN 的通用模…

eclipse maven 项目导入报错

错误&#xff1a;Internal compiler error: java.lang.NullPointerException at org.eclipse.jdt.internal.compiler.apt.dispatch.AnnotationDiscoveryVisitor 环境&#xff1a;eclipse Kepler Service Release 2 ,JDK1.7 解决办法&#xff1a;编码不对&#xff0c;修改

惠海H5118舞台灯芯片方案 RGBW共阳12V/24V/36V大功率 无频闪

H5118是一款外围电路简单的多功能平均电流型LED恒流驱动器&#xff0c;适用于5-48V电压范围的非隔离式大功率恒流LED驱动领域。芯片采用了平均电流模式控制&#xff0c;输出电流精度在3&#xff05;&#xff1b;输出电流对输入输出电压以及电感不敏感&#xff1b;芯片内部集成了…

鸿蒙开发岗位,面试到底问些啥?

随着春天的脚步临近&#xff0c;一年度的面试旺季却也已开始。就在2 月 28 日&#xff0c;”智联招聘崩了“登上微博热搜。有网友感叹&#xff0c;现在找工作太难了&#xff0c;发现有这么多人在竞争更焦虑了。 对此智联招聘回应称&#xff0c;由于求职流量新高&#xff0c;服务…

XWPFDocument中XmlCursor的使用

类名&#xff1a; org.apache.xmlbeans Interface XmlCursor版本&#xff1a; 原xml代码&#xff1a; <w:p w14:paraId"143E3662" w14:textId"4167FBA7" w:rsidR"001506F2" w:rsidRPr"003F3D89" w:rsidRDefault"001506F2&qu…

神经网络实战前言(补充)

深度学习 深度学习是特殊的机器学习&#xff0c;使用复杂的、多层神经网络进行学习。深度神经网络&#xff08;DNN&#xff09;&#xff0c;每层学习的信息的复杂度是不断增加的。例如面部识别&#xff0c;第一层识别眼睛、第二层识别鼻子&#xff0c;直到所有的面部特征识别完…