当前位置: 首页 > news >正文

【C++随笔02】左值和右值

【C++随笔02】左值和右值

  • 一、左值和右值
    • 1、字面理解——左值、右值
    • 2、字面理解的问题
    • 3、左值、右值
    • 4、左值的特征
    • 5、 右值的特征
    • 6、x++和++x是左值还是右值
    • 7、复合例子
    • 8、通常字面量都是一个右值,除字符串字面量以外:
  • 二、左值引用和右值引用
  • 三、左值引用
    • 1、常量左值引用
    • 2、制构造函数和复制赋值运算符函数——左值引用
  • 四、右值引用
    • 1、移动语义和完美转发
    • 2、移动语义
    • 3、完美转发
      • 3.1、简介、demo
      • 3.2、问题:c++中的完美转发(std::forward)存在的意义?
  • 简单总结

一、左值和右值

1、字面理解——左值、右值

最简单的字面理解,表达式等号左边的值为左值,等号右边的值为右值,比如

int x = 1; 
int y = 3; 
int z = x + y;

以上面的代码为例,

  1. x是左值,1是右值;
  2. y是左值,3是右值;
  3. z是左值,x+y的结果是右值。(注意,是结果)

2、字面理解的问题

在第一行代码中我们判断a是一个左值,它却在第二行变成了右值,所以这就是问题,要准确地区分左值和右值还是应该理解其内在含义。

3、左值、右值

在C++中

  • 左值一般是指一个指向特定内存的具有名称的值(具名对象),它有一个相对稳定的内存地址,并且有一段较长的生命周期。
  • 右值则是不指向稳定内存地址的匿名值(不具名对象)

简单来说,左值是一个有内存地址的表达式,而右值是一个没有内存地址的表达式。

基于这一特征,我们可以用取地址符&来判断左值和右值,能取到内存地址的值为左值,否则为右值。还是以上面的代码为例,因为&a和&b都是符合语法规则的,所以a和b都是左值。

4、左值的特征

左值具有以下特征:

  • 左值在内存中有唯一的地址。
  • 左值可以出现在赋值操作符的左边。
  • 左值可以被取地址操作符(&)获取其内存地址。
  • 左值可以作为函数参数或返回值。
int x = 10; // x是一个左值
int* ptr = &x; // 获取x的地址并赋给指针ptr

5、 右值的特征

右值具有以下特征:

  • 右值没有内存地址。
  • 右值不能作为赋值操作符的左边。
  • 右值不能被取地址操作符获取其内存地址。
int y = 20; // 20是一个右值
int z = x + y; // 表达式x + y的结果是一个右值

6、x++和++x是左值还是右值

int *p = &x++; // 编译失败 
int *q = &++x; // 编译成功
  • x++是右值,因为在后置++操作中编译器首先会生成一份x值的临时复制,然后才对x递增,最后返回临时复制内容。
  • ++x则不同,它是直接对x递增后马上返回其自身,所以++x是一个左值。

7、复合例子

int x = 1;
int get_val()
{return x;
}
void set_val(int val)
{x = val;
}
int main() 
{x++;++x;int y = get_val();set_val(6);
}
  • get_val函数,该函数返回了一个全局变量x,虽然很明显变量x是一个左值,但是它经过函数返回以后变成了一个右值。

原因和x++类似,在函数返回的时候编译器并不会返回x本身,而是返回x的临时复制,所以int * p = &get_val();也会编译失败。

  • set_val函数,该函数接受一个参数并且将参数的值赋值到x中。在main函数中set_val(6);实参6是一个右值,但是进入函数之后形参val却变成了一个左值。

我们可以对val使用取地址符.

  • 左值到右值的隐式转换
    左值可以被隐式地转换为右值,例如在某些表达式中,需要右值而传入一个左值参数时,编译器会自动进行转换。
void printValue(int value) 
{cout << value << endl;
}int x = 10;
printValue(x); // 编译器将x隐式地转换为右值传递给函数

8、通常字面量都是一个右值,除字符串字面量以外:

int x = 1;
set_val(6);
auto p = &“hello world”;

编译器会将字符串字面量存储到程序的数据段中,程序加载的时候也会为其开辟内存空间(rodata),所以我们可以使用取地址符&来获取字符串字面量的内存地址。

  • 给大家写一个有编译错误的例子,大家调调
#include <iostream>int add1(int& x)
{return x+1;
}int main() {int a = add1(1);std::cout << a << std::endl;return 0;
}

二、左值引用和右值引用

void processValue(int& value) {// 对左值进行处理
}void processValue(int&& value) {// 对右值进行处理
}
  • 左值引用和右值引用在C++11中,引入了右值引用的概念。左值引用(L-value references)用于绑定到左值,右值引用(R-value references)用于绑定到右值。

  • 左值引用的声明使用单个&符号:

int x = 10;
int& lvalueRef = x; // 左值引用绑定到左值x
  • 右值引用的声明使用两个&&符号:
int y = 20;
int&& rvalueRef = y + 30; // 右值引用绑定到右值表达式的结果

引用可以方便地对变量进行修改或者将其传递给函数。
右值引用在移动语义(Move Semantics)和完美转发(Perfect Forwarding)中具有重要的作用,可以提高性能和代码效率。

三、左值引用

1、常量左值引用

常量左值引用的特性显得更加有趣,它除了能引用左值,还能够引用右值,比如:

int &x1 = 7; // 编译错误
const int &x = 11; // 编译成功

在上面的代码中,第一行代码会编译报错,因为int&无法绑定一个int类型的右值,但是第二行代码却可以编译成功。请注意,虽然在结果上const int &x = 11和const int x = 11是一样的,但是从语法上来说,前者是被引用了,所以语句结束后11的生命周期被延长,而后者当语句结束后右值11应该被销毁。虽然常量左值引用可以引用右值的这个特性在赋值表达式中看不出什么实用价值,但是在函数形参列表中却有着巨大的作用。一个典型的例子就是复制构造函数和复制赋值运算符函数,

2、制构造函数和复制赋值运算符函数——左值引用

当我们使用左值引用时,通常会涉及到复制构造函数和复制赋值运算符函数。复制构造函数用于创建一个新对象,并将其初始化为已存在的对象的副本。复制赋值运算符函数用于将一个已存在的对象的值复制给另一个已存在的对象。

以下是一个简单的示例程序,演示了左值引用、复制构造函数和复制赋值运算符函数的使用:

#include <iostream>class MyObject {
private:int data;public:MyObject(int d) : data(d) {std::cout << "Constructor called with value: " << d << std::endl;}MyObject(const MyObject& other) : data(other.data) {std::cout << "Copy constructor called. Copied value: " << data << std::endl;}MyObject& operator=(const MyObject& other) {if (this != &other) {data = other.data;std::cout << "Copy assignment operator called. Copied value: " << data << std::endl;}return *this;}void printData() const {std::cout << "Data: " << data << std::endl;}
};int main() {MyObject obj1(42);                      // 调用构造函数MyObject obj2(obj1);                    // 调用复制构造函数MyObject obj3 = obj1;                   // 调用复制构造函数MyObject obj4(55);                      // 调用构造函数obj4 = obj1;                            // 调用复制赋值运算符函数obj1.printData();                        // 输出: Data: 42obj2.printData();                        // 输出: Data: 42obj3.printData();                        // 输出: Data: 42obj4.printData();                        // 输出: Data: 42return 0;
}

输出

Constructor called with value: 42
Copy constructor called. Copied value: 42
Copy constructor called. Copied value: 42
Constructor called with value: 55
Copy assignment operator called. Copied value: 42
Data: 42
Data: 42
Data: 42
Data: 42

在上述示例中,我们首先定义了一个名为 MyObject 的类,该类具有一个带有整数参数的构造函数、一个复制构造函数和一个复制赋值运算符函数。然后我们创建了几个 MyObject 类型的对象,并通过不同方式进行初始化和赋值。

在 main() 函数中,我们创建了 obj1,并使用拷贝构造函数将其值分别复制给 obj2 和 obj3。接下来,我们创建了 obj4,然后使用赋值运算符将 obj1 的值复制给 obj4。

最后,我们调用各个对象的成员函数 printData() 来打印它们的数据值。你可以看到,obj2、obj3 和 obj4 的数据值都与 obj1 相同,这表明复制构造函数和复制赋值运算符函数成功地将一个对象的值复制给了另一个对象。

四、右值引用

顾名思义,右值引用是一种引用右值且只能引用右值的方法。在语法方面右值引用可以对比左值引用,在左值引用声明中,需要在类型后添加&,而右值引用则是在类型后添加&&,例如:

int i = 0;
int &j = i; // 左值引用
int &&k = 11; // 右值引用

在上面的代码中,k是一个右值引用,如果试图用k引用变量i,则会引起编译错误。右值引用的特点之一是可以延长右值的生命周期。

1、移动语义和完美转发

右值引用在移动语义和完美转发中起着重要的作用。

  • 移动语义:移动语义是指通过右值引用将资源(如动态分配的内存、文件句柄等)从一个对象转移到另一个对象,而不是进行深拷贝。这样可以避免不必要的内存分配和释放,提高程序性能。

  • 完美转发:完美转发是指将一个函数中的参数以原样传递给另一个函数,包括参数的左值或右值属性信息。通过使用右值引用和模板,可以实现完美转发,避免了不必要的拷贝。

2、移动语义

当涉及到移动语义和完美转发时,我们需要先了解一些基本概念和问题。在C++中,对象的拷贝构造函数(Copy Constructor)和拷贝赋值运算符(Copy Assignment Operator)会对资源进行拷贝操作,这可能导致内存分配和释放的开销。在某些情况下,我们希望能够高效地转移资源的所有权而不是进行深拷贝,这就引入了移动语义和完美转发。

移动语义(Move Semantics)
移动语义是指通过右值引用将资源(如动态分配的内存、文件句柄等)从一个对象转移到另一个对象,而不是进行深拷贝。移动语义可以大大提高程序性能,因为它避免了不必要的内存分配和释放。

移动语义的实现依赖于右值引用。右值引用(R-value Reference)通过双个&&符号进行声明,并且可以绑定到右值。通过移动构造函数(Move Constructor)和移动赋值运算符(Move Assignment Operator),可以使用移动语义来实现资源的高效转移。

简单来说,移动语义允许我们从一个临时的右值对象或者一个将要被销毁的对象中“窃取”资源,然后将其传递给新对象,而无需进行资源的复制操作。

示例代码:

#include <iostream>class MyObject {
private:int data;public:MyObject(int d = 0) : data(d) {std::cout << "Constructor called with value: " << d << std::endl;}MyObject(const MyObject& other) : data(other.data) {std::cout << "Copy constructor called. Copied value: " << data << std::endl;}MyObject& operator=(const MyObject& other) {if (this != &other) {data = other.data;std::cout << "Copy assignment operator called. Copied value: " << data << std::endl;}return *this;}MyObject(MyObject&& other) noexcept : data(other.data) {std::cout << "Move constructor called. Moved value: " << data << std::endl;other.data = 0;  // 清空原对象的值}MyObject& operator=(MyObject&& other) noexcept {if (this != &other) {data = other.data;std::cout << "Move assignment operator called. Moved value: " << data << std::endl;other.data = 0;  // 清空原对象的值}return *this;}void printData() const {std::cout << "Data: " << data << std::endl;}
};int main() {MyObject obj1(42);                      // 调用构造函数MyObject obj2(obj1);                    // 调用复制构造函数MyObject obj3 = obj1;                   // 调用复制构造函数MyObject obj4(55);                      // 调用构造函数obj4 = obj1;                            // 调用复制赋值运算符函数MyObject obj5(std::move(obj1));         // 调用移动构造函数MyObject obj6 = std::move(obj2);        // 调用移动赋值构造函数obj1.printData();                        // 输出: Data: 42obj2.printData();                        // 输出: Data: 0obj3.printData();                        // 输出: Data: 42obj4.printData();                        // 输出: Data: 42obj5.printData();                        // 输出: Data: 42obj6.printData();                        // 输出: Data: 42return 0;
}

Constructor called with value: 42
Copy constructor called. Copied value: 42
Copy constructor called. Copied value: 42
Constructor called with value: 55
Copy assignment operator called. Copied value: 42
Move constructor called. Moved value: 42
Move constructor called. Moved value: 42
Data: 0
Data: 0
Data: 42
Data: 42
Data: 42
Data: 42

  • obj1和obj2为0,这证明了移动构造函数被调用,并且资源成功被转移。

3、完美转发

3.1、简介、demo

完美转发(perfect forwarding)是C++11引入的概念,用于在函数模板中将参数按原样传递给另一个函数,同时保留其值类别(lvalue或rvalue)。它可以在保持精确性的同时避免不必要的复制或移动操作,提高代码的效率。

完美转发通常与转发引用类型参数(如模板中的万能引用)一起使用,以实现泛型编程中的参数传递。在函数模板中,我们可以使用 std::forward 函数来进行完美转发。

下面是一个使用完美转发的示例:

#include <iostream>
#include <utility>// 定义一个接收传入参数的函数
void process(int& i) {std::cout << "Lvalue: " << i << std::endl;i = 100;  // 修改传入的左值参数
}void process(int&& i) {std::cout << "Rvalue: " << i << std::endl;
}// 将参数转发到 process 函数
template <typename T>
void wrapper(T&& arg) {process(std::forward<T>(arg));
}int main() {int a = 42;wrapper(a);        // 传递左值wrapper(123);      // 传递右值std::cout << "a: " << a << std::endl;int b = 42;process(b);process(123);std::cout << "b: " << a << std::endl;return 0;
}

输出
Lvalue: 42
Rvalue: 123
a: 100
Lvalue: 42
Rvalue: 123
b: 100

在上述示例中,我们定义了两个重载的 process 函数,一个接受左值引用参数,一个接受右值引用参数。然后,我们创建了一个模板函数 wrapper,该函数接受一个通用引用类型的参数 T&& arg。

在 wrapper 函数内部,我们通过调用 std::forward 来进行完美转发,将 arg 参数原封不动地传递给 process 函数。std::forward 根据参数的值类别(lvalue还是rvalue)将参数作为对应类型的引用进行转发。

在 main 函数中,我们先传递了一个左值 x 给 wrapper 函数,然后传递了一个右值 123。程序会根据参数的值类别,选择调用合适的 process 函数,并输出相应的结果。

使用完美转发可以避免不必要的拷贝和移动操作,提高代码的效率和性能。

3.2、问题:c++中的完美转发(std::forward)存在的意义?

  • 我们从上面的demo中可以看到,既然不使用forward也可以达到类似的效果,那为何还要使用完美转发(std::forward)呢?

  • 说这个问题前,我们先把上面的一个demo改下

#include <iostream>class MyObject {
private:int data;public:MyObject(int d = 0) : data(d) {std::cout << "Constructor called with value: " << d << std::endl;}MyObject(const MyObject& other) : data(other.data) {std::cout << "Copy constructor called. Copied value: " << data << std::endl;}MyObject& operator=(const MyObject& other) {if (this != &other) {data = other.data;std::cout << "Copy assignment operator called. Copied value: " << data << std::endl;}return *this;}MyObject(MyObject&& other) noexcept : data(other.data) {std::cout << "Move constructor called. Moved value: " << data << std::endl;other.data = 0;  // 清空原对象的值}MyObject& operator=(MyObject&& other) noexcept {if (this != &other) {data = other.data;std::cout << "Move assignment operator called. Moved value: " << data << std::endl;other.data = 0;  // 清空原对象的值}return *this;}void printData() const {std::cout << "Data: " << data << std::endl;}
};template<typename T>
T* createObject(T&& t)
{return new MyObject(t);
}int main() {MyObject* newMyObject = createObject(std::move(MyObject(110)));return 0;
}
  • 大家猜猜看,上面应该输出什么?应该调用移动构造函数的,对吧,实际情况输出如下,调用的却是拷贝构造函数。

Constructor called with value: 110
Copy constructor called. Copied value: 110

  • 是不是很好奇,为啥调用的是拷贝构造函数,而非我们之前想象的移动构造函数呢?
    我们把createObject做下简单的更改,增加std::forward,
template<typename T>
T* createObject(T&& t)
{return new MyObject(std::forward<T>(t));
}
  • 结果输出如下

Constructor called with value: 110
Move constructor called. Moved value: 110

这时,才真正的如我们所想,真的调用了移动构造函数。

  • 分析:经历了模版参数t这一次转发,t右值的属性被改变为了左值。

简单总结

  • 左值引用用于引用左值并允许修改,
  • 右值引用用于引用右值并具有移动语义和完美转发的特性。

相关文章:

【C++随笔02】左值和右值

【C随笔02】左值和右值 一、左值和右值1、字面理解——左值、右值2、字面理解的问题3、左值、右值4、左值的特征5、 右值的特征6、x和x是左值还是右值7、复合例子8、通常字面量都是一个右值&#xff0c;除字符串字面量以外&#xff1a; 二、左值引用和右值引用三、左值引用1、常…...

几个nlp的小任务(多选问答)

@TOC 安装库 多选问答介绍 定义参数、导入加载函数 缓存数据集 随机选择一些数据展示 进行数据预处理部分(tokenizer) 调用t...

【C++学习记录】为什么需要异常处理,以及Try Catch的使用方法

1.什么是异常&#xff0c;什么是错误&#xff1f; 程序无法保证100%正确运行&#xff0c;万无一失。有的错误在编译时能发现&#xff0c;比如&#xff1a;关键字拼写、变量名未定义、括号不配对、语句末尾缺分号等。这是在编译阶段发现的&#xff0c;称为编译错误。 有的能正常…...

孪生网络(Siamese Network)

基本概念 孪生网络&#xff08;Siamese Network&#xff09;是一类神经网络结构&#xff0c;它是由两个或更多个完全相同的网络组成的。孪生网络通常被用于解决基于相似度比较的任务&#xff0c;例如人脸识别、语音识别、目标跟踪等问题。 孪生网络的基本思想是将输入数据同时…...

【Redis】Redis是什么、能干什么、主要功能和工作原理的详细讲解

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;目前学习C/C、算法、Python、Java等方向&#xff0c;一个正在慢慢前行的普通人。 &#x1f3c0;系列专栏&#xff1a;陈童学的日记 &#x1f4a1;其他专栏&#xff1a;CSTL&…...

8月26日,每日信息差

1、上海发布两项支持高级别自动驾驶的5G网络标准&#xff0c;在上海市通管局的指导下&#xff0c;由上海移动和中国信息通信研究院牵头组织二十余家标准起草单位共同参与编写的《支持高级别自动驾驶的5G网络规划建设和验收要求》和《支持高级别自动驾驶的5G网络性能要求》等两项…...

云和恩墨面试(部分)

一面 软件架构设计方案应该包含哪些内容&#xff0c;哪些维度 二面 架构师如何保证软件产品质量线程屏障(或者说线程栅栏)是什么&#xff0c;为什么要使用线程屏障事务传播⾏为为NESTED时&#xff0c;当内部事务发生异常时&#xff0c;外部事务会回滚吗&#xff1f;newBing:…...

volatile 关键字详解

目录 volatile volatile 关键用在什么场景下&#xff1a; volatile 关键字防止编译器优化&#xff1a; volatile 是一个在许多编程语言中&#xff08;包括C和C&#xff09;用作关键字的标识符。它用于告诉编译器不要对带有该关键字修饰的变量进行优化&#xff0c;以确保变量在…...

Ceph入门到精通-大流量10GB/s LVS+OSPF 高性能架构

LVS 和 LVSkeepalived 这两种架构在平时听得多了&#xff0c;最近才接触到另外一个架构LVSOSPF。这个架构实际上是LVSKeepalived 的升级版本&#xff0c;我们所知道LVSKeepalived 架构是这样子的&#xff1a; 随着业务的扩展&#xff0c;我们可以对web服务器做水平扩展&#xf…...

Unity光照相关

1. 光源类型 Unity支持多种类型的光源&#xff0c;包括&#xff1a; 1. 点光源&#xff08;Point Light&#xff09;&#xff1a;从一个点向四周发射光线&#xff0c;适用于需要突出物体的光源。 2. 平行光&#xff08;Directional Light&#xff09;&#xff1a;从无限远处…...

Qt基本类型

QT基本数据类型定义在#include <QtGlobal> 中&#xff0c;QT基本数据类型有&#xff1a; 类型名称注释备注qint8signed char有符号8位数据qint16signed short16位数据类型qint32signed short32位有符号数据类型qint64long long int 或(__int64)64位有符号数据类型&#x…...

前端基础(Element、vxe-table组件库的使用)

前言&#xff1a;在前端项目中&#xff0c;实际上&#xff0c;会用到组件库里的很多组件&#xff0c;本博客主要介绍Element、vxe-table这两个组件如何使用。 目录 Element 引入element 使用组件的步骤 使用对话框的示例代码 效果展示 vxe-table 引入vxe-table 成果展…...

C++学习记录——이십팔 C++11(4)

文章目录 包装器1、functional2、绑定 这一篇比较简短&#xff0c;只是因为后要写异常和智能指针&#xff0c;所以就把它单独放在了一篇博客&#xff0c;后面新开几篇博客来写异常和智能指针 包装器 1、functional 包装器是一个类模板&#xff0c;对可调用对象类型进行再封装…...

UE学习记录03----UE5.2 使用拖拽生成模型

0.创建蓝图控件&#xff0c;自己想要展示的样子 1.侦测鼠标拖动 2.创建拖动操作 3.拖动结束时生成模型 3.1创建actor , 创建变量EntityMesh设为可编辑 生成Actor&#xff0c;创建变量EntityMesh设为可编辑 屏幕鼠标位置转化为3D场景位置 4.将texture设置为变量并设为可编辑&am…...

Spring Cache框架(缓存)

1、介绍&#xff1a; Spring Cache 是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要简单加个注解&#xff0c;就能实现缓存功能。它提供了一层抽象&#xff0c;底层可以切换不同的cache实现。具体就是通过CacheManager 接口来实现不同的缓存技术。 针对不同…...

Linux学习之Ubuntu 20使用systemd管理OpenResty服务

sudo cat /etc/issue可以看到操作系统的版本是Ubuntu 20.04.4 LTS&#xff0c;sudo lsb_release -r可以看到版本是20.04&#xff0c;sudo uname -r可以看到内核版本是5.5.19&#xff0c;sudo make -v可以看到版本是GNU Make 4.2.1。 需要先参考我的博客《Linux学习之Ubuntu 2…...

[数据集][目标检测]疲劳驾驶数据集VOC格式4类别-4362张

数据集格式&#xff1a;Pascal VOC格式(不包含分割的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;4362 标注数量(xml文件个数)&#xff1a;4362 标注类别数&#xff1a;4 标注类别名称:["closed_eye","closed_mouth"…...

matlab使用教程(25)—常微分方程(ODE)选项

1.ODE 选项摘要 解算 ODE 经常要求微调参数、调整误差容限或向求解器传递附加信息。本主题说明如何指定选项以及每个选项与哪些微分方程求解器兼容。 1.1 选项语法 使用 odeset 函数创建 options 结构体&#xff0c;然后将其作为第四个输入参数传递给求解器。例如&#xff0…...

MybatisPlus简单到入门

一、MybatisPlus简介 1、入门案例&#xff08;重点&#xff09;&#xff1a; 1.SpringBoot整合MP1).创建新模块选择&#xff0c;Spring项初始化。2).选择当前模块使用的技术&#xff0c;只保留MySQL Driver就行&#xff0c;不要选择mybatis避免与后面导入mybatisPlus的依赖发…...

9. 优化器

9.1 优化器 ① 损失函数调用backward方法&#xff0c;就可以调用损失函数的反向传播方法&#xff0c;就可以求出我们需要调节的梯度&#xff0c;我们就可以利用我们的优化器就可以根据梯度对参数进行调整&#xff0c;达到整体误差降低的目的。 ② 梯度要清零&#xff0c;如果梯…...

go学习之流程控制语句

文章目录 流程控制语句1.顺序控制2.分支控制2.1单分支2.2双分支单分支和双分支的四个题目switch分支结构 3.循环控制for循环控制while 和do...while的实现 4.跳转控制语句breakcontinuegotoreturngotoreturn 流程控制语句 介绍&#xff1a;在程序中&#xff0c;程序运行的流程…...

docker基于已有容器和通过Dockerfile进行制作镜像配置介绍

目录 一.制作镜像的两种方式 1.在已有容器中更新并提交这个镜像 2.使用Dockerfile来制作 二.基于容器制作镜像 1.格式 &#xff08;1&#xff09;主要格式 &#xff08;2&#xff09;可选参数 2.案例 基于容器创建镜像设置标签并进行验证是否可用 &#xff08;1&…...

2022年09月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;最长上升子序列 一个数的序列bi&#xff0c;当b1 < b2 < … < bS的时候&#xff0c;我们称这个序列是上升的。对于给定的一个序列(a1, a2, …, aN)&#xff0c;我们可以得到一些上升的子序列(ai1, ai2, …, aiK)&#xff0c;这里1 < i1 < i2 &…...

二级MySQL(九)——表格数据处理练习

在Mysql中&#xff0c;可以用INSERT或【REPLACE】语句&#xff0c;向数据库中已一个已有的表中插入一行或多行记录。 在Mysql中&#xff0c;可以用【DELETE】或【TRUNCATE】语句删除表中的所有记录。 在Mysql中&#xff0c;可以用【UPDATE】语句来修改数据表中的记录。 为了完…...

QT ListQvector at赋值出错以及解决办法 QT基础入门【QT存储结构】

1、问题 error: passing const QString as this argument discards qualifiers error: assignment of read-only location vec.QVector<int>::at(0) 在Qt中QList,Qvector一般获取元素都是通过at(index)来获取,但是at()的返回是一个const & 常引用,也就是元素不支…...

STM32 CubeMX (H750)RGB屏幕 LTDC

STM32 CubeMX STM32 RGB888 LTDC STM32 CubeMX一、STM32 CubeMX 设置时钟树LTDC使能设置屏幕参数修改RGB888的GPIO 二、代码部分效果 RGB屏幕线束定义&#xff1a; 一、STM32 CubeMX 设置 时钟树 这里设置的时钟&#xff0c;关于刷新速度 举例子&#xff1a;LCD_CLK24MHz 时…...

Redis问题集合(三)在Redis容器里设置键值对

前言 前提是已经拉取了Redis镜像并创建了对应的容器做个记录&#xff0c;方便后续查看 步骤 查看Redis容器的ID&#xff1a;docker ps -a 进入容器&#xff1a;docker exec -it 容器ID /bin/bash进入redis命令行&#xff1a;redis-cli输入密码&#xff1a;auth 配置密码 查看…...

spark中排查Premature EOF: no length prefix available

报错信息 /07/22 10:20:28 WARN DFSClient: Error Recovery for block BP-888461729-172.16.34.148-1397820377004:blk_15089246483_16183344527 in pipeline 172.16.34.64:50010, 172.16.34.223:50010: bad datanode 172.16.34.64:50010 [DataStreamer for file /bdp/data/u9…...

numpy高级函数之where和extract函数

1 numpy.where() 函数返回输入数组中满足给定条件的元素的索引 ---------------------------------------------------- 代码&#xff1a; n1np.random.randint(10,20,10) n2np.where(n1>15) 结果&#xff1a; [17 15 19 15 12 10 16 11 15 13] #原始数组 (array([…...

用Python写一个武侠游戏

前言 在本教程中&#xff0c;我们将使用Python写一个武侠类的游戏&#xff0c;大的框架全部搭好了&#xff0c;很多元素都可以自己添加&#xff0c;让游戏更丰富 &#x1f4dd;个人主页→数据挖掘博主ZTLJQ的主页 个人推荐python学习系列&#xff1a; ☄️爬虫JS逆向系列专栏 -…...

wordpress文章页透明/软文营销的作用

需求描述 问题&#xff1a;subquery 1 union subquery2&#xff0c;其中union左右的两个子查询是否并行。 场景&#xff1a;业务中性能敏感的业务&#xff0c;希望能加快速度&#xff0c;如果数据库能两个子查询并行执行&#xff0c;既可以节省时间&#xff0c;还可以节省网络…...

可信网站申请/厦门网站建设

Libevent内存管理相当简单。可以支持用于自定义的内存分配策略&#xff0c;这个时候就是用户自己写对应的内存分配策略例如可以写个简单的内存池&#xff0c;然后注册回调函数&#xff0c;供内存分配调用&#xff1b;也可以通过系统自带的malloc、realloc、free分配内存。可以通…...

大型地方门户网站源码/seo网络贸易网站推广

流程控制是每种编程语言控制逻辑走向和执行次序的重要部分&#xff0c;流程控制可以说是一门语言的“经脉”。Go语言中最常用的流程控制有if和for&#xff0c;而switch和goto主要是为了简化代码、降低重复代码而生的结构&#xff0c;属于扩展类的流程控制。if else(分支结构)if…...

深圳网站建设骏域网站建设/宁波网站推广制作

java问题 定义一个Point点类定义一个Point点类&#xff0c;成员变量有x,y,成员函数set()设置x,y的值&#xff0c;get()获取x,y的值&#xff0c;并定义一个点对象调用set()和get(),并定义一个点对象调用set()和get()构造方法重载&#xff0c;distance()表示2点间的距离。实例pub…...

做卖车的网站有哪些/百度一下百度搜索官网

基本数据类型转换 基本介绍 Golang 和 java / c 不同&#xff0c;Go 在不同类型的变量之间赋值时需要显式转换。也就是说 Golang 中数据类型不能自动转换。基本语法表达式 T(v) 将值 v 转换为类型 T T&#xff1a; 就是数据类型&#xff0c;比如 int32&#xff0c;int64&…...

wordpress nginx伪静态/最让顾客心动的促销活动

目前已发行的版本有1.0、1.1、2.0、3.0、3.5、4.0、4.5&#xff08;及4.5.1、4.5.2&#xff09;、4.6&#xff08;及4.6.1&#xff09;。 1.0版本&#xff1a;最初的.net framework版本&#xff0c;作为一个独立的工具包存在。 1.1版本&#xff1a;是1.1的升级版本&#xff0c;…...