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

Operator <=> (spaceship operator)

operator <=>动机

在C++20以前定义比较运算符:其他比较运算符基于<和==实现

struct Type {int value;// 相等运算符friend bool operator==(const Type& a, const Type& b) {return a.value == b.value;}// 不等运算符friend bool operator!=(const Type& a, const Type& b) {return !(a == b);}// 小于运算符friend bool operator<(const Type& a, const Type& b) {return a.value < b.value;}// 其他比较运算符基于<和==实现friend bool operator>(const Type& a, const Type& b) {return b < a; // 通过交换参数重用operator<}friend bool operator<=(const Type& a, const Type& b) {return !(b < a); // a <= b 等价于 !(b < a)}friend bool operator>=(const Type& a, const Type& b) {return !(a < b); // a >= b 等价于 !(a < b)}
};

问题是,尽管大多数操作符都是根据其他操作符定义的(都基于operator == 或operator <),但
这些定义很繁琐,而且会增加很多阅读上的混乱。
此外,对于实现良好的类型,可能需要更多的声明:
• 若操作符不能抛出,就用noexcept 声明
• 若操作符可以在编译时使用,则使用constexpr 声明
• 若构造函数不是显式的,则将操作符声明为“隐藏友元”(在类结构中与友元一起声明,以便
两个操作数都成为参数,并支持隐式类型转换)
• 声明带有[[nodiscard]] 的操作符,以便在返回值未使用时强制发出警告

struct Type {int value;// 隐式构造函数(根据需求决定是否explicit)Type(int v) noexcept : value(v) {}// 核心比较运算符(隐藏友元 + [[nodiscard]] + noexcept + constexpr)[[nodiscard]] friend constexpr bool operator==(const Type& a, const Type& b) noexcept {return a.value == b.value;}[[nodiscard]] friend constexpr bool operator<(const Type& a, const Type& b) noexcept {return a.value < b.value;}// 以下运算符通过核心运算符复用(隐藏友元 + 属性传递)[[nodiscard]] friend constexpr bool operator!=(const Type& a, const Type& b) noexcept {return !(a == b);}[[nodiscard]] friend constexpr bool operator>(const Type& a, const Type& b) noexcept {return b < a;}[[nodiscard]] friend constexpr bool operator<=(const Type& a, const Type& b) noexcept {return !(b < a);}[[nodiscard]] friend constexpr bool operator>=(const Type& a, const Type& b) noexcept {return !(a < b);}
};

C++20 后如何定义比较运算符。

== 与!= 操作符

为了检查是否相等,现在定义== 操作符就够了。
当编译器找不到表达式的匹配声明a!=b 时,编译器会重写表达式并查找!(a==b)。若这不起作
用,编译器也会尝试改变操作数的顺序,所以也会尝试!(b==a):

 operator <=>

The effect is that both operators use their default implementation, which compares objects member by member.

Notes that member function must be const and that the parameter must be declared to be a const lvalue reference (const &).

 Friend functions might alternatively take both parameters by value.

The return type of operator<=> is not an integral value. The return type is a type that signals the comparison category, which could be strong ordering, weak ordering, or partial ordering. These types support the comparison with 0 to deal with the result.

In addition, even when declaring the operator as a member function, the following applies for the generated operators:

• They are noexcept if comparing the members never throws

• They are constexpr if comparing the members is possible at compile time

• Thanks to rewriting, implicit type conversions for the first operand are also supported.

This reflects that, in general, operator== and operator<=> handle different but related things:

operator== defines equality and can be used by the equality operators == and !=.

operator<=> defines the ordering and can be used by the relational operators <, <=, >, and >=.

 TSL中已经删除了6中比较运算符

 

#include <iostream>struct Type
{auto operator <=> (const Type&) const = default;long id{};
};int main(void)
{Type a{10};Type b{20};auto ret = a == b;std::cout << std::boolalpha << ret << std::endl;return 0;
}

创建一个不区分大小写的字符串类型 CIString 的示例,该类型既可以与自身比较,也可以与 const char* 进行比较:

In C++17, this requires 18 comparison functions:

class CIString {std::string s;public:friend bool operator==(const CIString& a, const CIString& b) { ...}friend bool operator!=(const CIString& a, const CIString& b) { ... }friend bool operator> (const CIString& a, const CIString& b) { ... }friend bool operator>=(const CIString& a, const CIString& b) { ... }friend bool operator<(const CIString& a, const CIString& b) { ... }friend bool operator<=(const CIString& a, const CIString& b) { ... }friend bool operator==(const CIString& a, const char* b) { ... }friend bool operator< (const CIString& a, const char* b) { ... }friend bool operator!=(const CIString& a, const char* b) { ... }friend bool operator> (const CIString& a, const char* b) { ... }friend bool operator>=(const CIString& a, const char* b) { ... }friend bool operator<=(const CIString& a, const char* b) { ... }friend bool operator==(const char* a, const CIString& b) { ... }friend bool operator< (const char* a, const CIString& b) { ... }friend bool operator!=(const char* a, const CIString& b) { ... }friend bool operator> (const char* a, const CIString& b) { ... }friend bool operator>=(const char* a, const CIString& b) { ... }friend bool operator<=(const char* a, const CIString& b) { ... }};

In C++20, this requires only 4:

#include <iostream>
#include <string>
#include <string.h>int ci_compare(const char* p1, const char* p2)
{return strcmp(p1, p2);
}class CIString {
public:std::string s;bool operator==(const CIString& b) const {return s.size() == b.s.size() &&ci_compare(s.c_str(), b.s.c_str()) == 0;}std::weak_ordering operator<=>(const CIString& b) const {return ci_compare(s.c_str(), b.s.c_str()) <=> 0;}bool operator==(char const* b) const {return ci_compare(s.c_str(), b) == 0;}std::weak_ordering operator<=>(const char* b) const {return ci_compare(s.c_str(), b) <=> 0;}
};int main(void)
{CIString cis1{"CIString test1"};CIString cis2{"CIString test2"};const char* ccp = "ccccc";auto r1 = cis1 == cis2;auto r2 = cis1 == ccp;auto r3 = ccp == cis2;auto r4 = (cis1 <=> cis2 < 0);auto r5 = (cis1 <=> ccp < 0);std::cout << std::boolalpha << r1 << ' ' << r2 << ' ' << r3 << ' ' << r4 << ' ' << r5 << std::endl;
}

Defaulted operator<=> Implies Defaulted operator==

If and only if an operator<=> member is defined as defaulted, then by definition a corresponding operator== member is also defined if no defaulted operator== is provided. All aspects (visibility, virtual, attributes, requirements, etc.) are adopted. For example:

class Type {...public:[[nodiscard]] virtual std::strong_orderingoperator<=>(const Type&) const requires(!std::same_as<T,bool>) = default;};

is equivalent to the following:

template<typename T>class Type {...public:[[nodiscard]] virtual std::strong_orderingoperator<=> (const Type&) const requires(!std::same_as<T,bool>) = default;[[nodiscard]] virtual booloperator== (const Type&) const requires(!std::same_as<T,bool>) = default;};

operator == implies operator !=

For TypeA and TypeB:

struct TypeA
{   long id{};
};struct TypeB
{   long id{};
};bool operator==(const TypeA& a, const TypeB& b) noexcept
{return a.id == b.id;
}TypeA a; TypeB b;a == b; // OK: fits perfectlyb == a; // OK, rewritten as: a == ba != b; // OK, rewritten as: !(a == b)b != a; // OK, rewritten as: !(a == b)

Before C+20, you also need to implement following function:

bool operator==(const TypeB&, const TypeA&) noexcept{ … }bool operator!=(const TypeA&, const TypeB&) noexcept{ … }bool operator!=(const TypeB&, const TypeA&) noexcept{ … }

 

//C++17
#include <iostream>struct TypeA
{long id{};
};
struct TypeB
{long id{};
};
bool operator==(const TypeA& a, const TypeB& b) noexcept
{return a.id == b.id;
}
bool operator==(const TypeB& b, const TypeA& a) noexcept
{return a.id == b.id;
}
bool operator!=(const TypeA& a, const TypeB& b) noexcept
{return a.id != b.id;
}
bool operator!=(const TypeB& b, const TypeA& a) noexcept
{return a.id != b.id;
}
int main(void)
{TypeA a;TypeB b;auto r1 = a == b; // OK: fits perfectlyauto r2 = b == a; // OK, rewritten as: a == bauto r3 = a != b; // OK, rewritten as: !(a == b)auto r4 = b != a; // OK, rewritten as: !(a == b)std::cout << std::boolalpha << r1 << ' ' << r2 << ' ' << r3 << ' ' << r4 << std::endl;return 0;
}// C++20
#include <iostream>struct TypeA
{long id{};
};
struct TypeB
{long id{};
};
bool operator==(const TypeA& a, const TypeB& b) noexcept
{return a.id == b.id;
}int main(void)
{TypeA a;TypeB b;auto r1 = a == b; // OK: fits perfectlyauto r2 = b == a; // OK, rewritten as: a == bauto r3 = a != b; // OK, rewritten as: !(a == b)auto r4 = b != a; // OK, rewritten as: !(a == b)std::cout << std::boolalpha << r1 << ' ' << r2 << ' ' << r3 << ' ' << r4 << std::endl;return 0;
}// C++20: compare TypaA with TypeB
#include <iostream>
#include <compare>struct TypeB
{long id{};
};struct TypeA
{bool operator==(const TypeB& b) const noexcept{return this->id == b.id;}auto operator<=>(const TypeB& b) const noexcept{return this->id <=> b.id;}long id{};
};int main(void)
{TypeA a;TypeB b;auto r1 = a == b; // OK: fits perfectlyauto r2 = b == a; // OK, rewritten as: a == bauto r3 = a != b; // OK, rewritten as: !(a == b)auto r4 = b != a; // OK, rewritten as: !(a == b)std::cout << std::boolalpha << r1 << ' ' << r2 << ' ' << r3 << ' ' << r4 << std::endl;return 0;
}
Implementing Operator <=>

You can define operator== and operator<=> yourself.

struct Context
{long Id;bool isSa{false};bool isNsa{false};…… //other fileds// for equality operators:bool operator== (const Context& rhs) const noexcept{return Id == rhs.Id; // defines equality (== and !=)}// for relational operators:auto operator <=> (const Context& rhs) const  noexcept{returneId <=> rhs.Id; //defines ordering (<, <=, >, and >=)}};

For UeContext x and y:

if   

x <= y  

does not find a matching definition of operator<=, it might be rewritten as

(x <=> y) <= 0   

or even   

0 <= (y <=> x)

As you can see by this rewriting, the new operator<=> performs a three-way comparison, which yields a value you can compare with 0:

• If the value of x<=>y is equal to 0, x and y are equal or equivalent.

• If the value of x<=>y is less than 0, x is less than y.

• If the value of x<=>y is greater than 0, x is greater than y.

The new operator <=> does not return a Boolean value. Instead, the return type is a type that signals the comparison category, which could be std::strong_ordering, std::weak_ordering or std::partial_ordering.

These types support the comparison with 0 to deal with the result.

One of the annoying difficulties in C++17 was actually writing out member-wise lexicographical comparisons. 

Use operator <=>

 

//C++20
#include <iostream>
#include <compare>
#include <tuple>struct A {int t;int u;int v;bool operator==(A const& rhs) const{return std::tie(t, u, v) == std::tie(rhs.t, rhs.u, rhs.v);}std::strong_ordering operator<=>(A const& rhs) const{// compare the T'sif (auto c = t <=> rhs.t; c != 0) return c;// .., then the U'sif (auto c = u <=> rhs.u; c != 0) return c;// ... then the V'sreturn v <=> rhs.v;}
};int main(void)
{A a1{10, 20, 30};A a2{10, 20, 30};std::cout << (a1 == a2) << std::endl;//Operator <=> takes precedence over all other comparison operatorsstd::cout << (a1 <=> a2 < 0) << std::endl;
}

 比较类别类型

<=> 操作符不返回布尔值,但其作用类似于三向比较,产生负值表示信号较少,正值表示信号
较大,0 表示信号相等或等效。这种行为类似于C 函数strcmp() 的返回值,也有一个重要的区别: 返
回值不是整数值,C++ 标准库提供了三种可能的返回类型,其反映了相应的比较类别。
比较类别
当比较两个值并按顺序排列时,有可能发生不同的“类别”行为:
• 对于强排序(也称为全排序),给定类型的值都小于或等于或大于该类型的其他值(包括其本
身)。
这一类的典型例子是整数值或常见的字符串类型,字符串s1 小于等于或大于字符串s2。
若此类别的一个值既不小于也不大于另一个值,则两个值相等。若有多个对象,可以按升序
或降序进行排序(相等值的顺序任意)。
• 对于弱排序,给定类型的任何值都小于、等于或大于该类型的任何其他值(包括其本身),
相等的值不一定是相等的(具有相同的值)。

此类别的典型示例是用于不区分大小写的字符串的类型,字符串”hello” 小于”hello1” 且大
于”hell”。尽管,”hello” 与”HELLO” 这两个字符串不相等但等价
若这个类别的值既不小于也不大于另一个值,那么这两个值至少是相等的(甚至可能是相等
的)。若有多个对象,则可以按升序或降序进行排序(相等值的顺序可以任意)。
• 对于偏排序,给定类型的任何值都可以小于、等于或大于该类型的任何其他值(包括其本身),
可能根本不能指定两个值之间的特定顺序。
这种类型的典型示例是浮点类型
,因为可能需要处理特殊值NaN(“非数字”),任何值与NaN
的比较结果都为false。因此,比较可能导致两个值是无序的,并且比较操作符可能返回四个
值中的一个。

若有多个对象,可能无法按升序或降序对其进行排序(除非确保不存在无法排序的值)。

使用标准库比较类别
• std::strong_ordering 的值:
– std::strong_ordering::less
– std::strong_ordering::equal (也可是std::strong_ordering::equivalent)
– std::strong_ordering::greater
• std::weak_ordering 的值:
– std::weak_ordering::less
– std::weak_ordering::equivalent
– std::weak_ordering::greater
• std::partial_ordering 的值:
– std::partial_ordering::less
– std::partial_ordering::equivalent
– std::partial_ordering::greater
– std::partial_ordering::unordered
注意,所有类型都有less、greater 和equivalent 值。但strong_ordering 也有equal,这与这里的
equal 相同,而partial_ordering 的值为unordered,既不表示小于,等于和大于。
较强比较类型具有向较弱比较类型的隐式类型转换, 可以将strong_ordering 值用作
weak_ordering 值,或partial_ordering 值(相等则为equivalent)。

NaN an example with a partial ordering

Consider wanting to add a NaN state to int, where a NaN is simply not ordered with any engaged value. We can do this with std::optional as storage as follows:

 

struct IntNan 
{std::optional<int> val = std::nullopt;bool operator==(IntNan const& rhs) const {if (!val || !rhs.val) {return false;}return *val == *rhs.val;}partial_ordering operator<=>(IntNan const& rhs) const {if (!val || !rhs.val) {//we can express the unordered state as a first class valuereturn partial_ordering::unordered;}// <=> over int returns strong_ordering, but this is// implicitly convertible to partial_orderingreturn *val <=> *rhs.val;}
};
IntNan{2} <=> IntNan{4}; // partial_ordering::less
IntNan{2} <=> IntNan{};  // partial_ordering::unorderedIntNan{2} < IntNan{4};   // true
IntNan{2} < IntNan{};    // false
IntNan{2} == IntNan{};   // false
IntNan{2} <= IntNan{};   // falsestrong_ordering::less < 0     // true
strong_ordering::less == 0    // false
strong_ordering::less != 0    // true
strong_ordering::greater >= 0 // truepartial_ordering::less < 0    // true
partial_ordering::greater > 0 // true// unordered is a special value that isn't
// comparable against anything
partial_ordering::unordered < 0  // false
partial_ordering::unordered == 0 // false
partial_ordering::unordered > 0  // false

 学生成绩在班级和年级中的排名,当学生成绩没有出来时无法比较

//student score, class and school
#include <iostream>
#include <compare>
#include <optional>struct IntNan 
{std::optional<int> val = std::nullopt;bool operator==(IntNan const& rhs) const {if (!val || !rhs.val) {return false;}return *val == *rhs.val;}std::partial_ordering operator<=>(IntNan const& rhs) const {if (!val || !rhs.val) {//we can express the unordered state as a first class valuereturn std::partial_ordering::unordered;}// <=> over int returns strong_ordering, but this is// implicitly convertible to partial_orderingreturn *val <=> *rhs.val;}
};int main(void)
{// partial_ordering::lessstd::cout << (IntNan{2} <=> IntNan{4} < 0) << std::endl; // partial_ordering::unorderedstd::cout << (IntNan{2} <=> IntNan{} == std::partial_ordering::unordered) << std::endl; std::cout << (IntNan{2} < IntNan{4}) << std::endl;   // truestd::cout << (IntNan{2} < IntNan{}) << std::endl;    // falsestd::cout << (IntNan{2} == IntNan{}) << std::endl;   // falsestd::cout << (IntNan{2} <= IntNan{}) << std::endl;   // false}

处理多种排序条件

要基于多个属性计算运算符<=> 的结果,通常可以实现一连串的子比较,直到结果不相等或到
达要最终属性的比较:

但若属性具有不同的比较类别,则返回类型不会编译。例如,若成员名是string 类型,而成员
值是double 类型,则返回类型会冲突: 

 

可以使用到最弱比较类型的转换。若已知最弱的比较类型,可以声明为返回类型: 

 

若不知道比较类型(例如, 类型是模板形参), 可以使用新的类型特征
std::common_comparison_category<> 来计算最强的比较类型:

 

通过使用尾部返回类型语法(auto 在前面,返回类型在-> 后面),可以使用参数来计算比较类型。
这种情况下,可以只使用name,而非rhs.name,这种方法通常是有效的(例如,也适用于独立函数)。
若希望提供比内部使用的类别更强的类别,则必须将内部比较的所有可能值映射到返回类型的
值。若不能映射某些值,这可能包括一些错误处理。例如:

#include <iostream>
#include <string>
#include <compare>
#include <cassert>#if 1
struct Person 
{
std::string name;
double value;std::partial_ordering operator<=> (const Person& rhs) const { // OKauto cmp1 = name <=> rhs.name;if (cmp1 != 0) return cmp1; // strong_ordering converted to return typereturn value <=> rhs.value; // partial_ordering used as the return type}
};
#endif#if 0
struct Person 
{
std::string name;
double value;auto operator<=> (const Person& rhs) const // OK-> std::common_comparison_category_t<decltype(name <=> rhs.name),decltype(value <=> rhs.value)> {auto cmp1 = name <=> rhs.name;if (cmp1 != 0) return cmp1; // used as or converted to common comparison typereturn value <=> rhs.value; // used as or converted to common comparison type}
};
#endif#if 0
struct Person {
std::string name;
double value;std::strong_ordering operator<=> (const Person& rhs) const {auto cmp1 = name <=> rhs.name;if (cmp1 != 0) return cmp1; // return strong_ordering for std::stringauto cmp2 = value <=> rhs.value; // might be partial_ordering for double// map partial_ordering to strong_ordering:assert(cmp2 != std::partial_ordering::unordered); // RUNTIME ERROR if unorderedreturn cmp2 == 0 ? std::strong_ordering::equal: cmp2 > 0 ? std::strong_ordering::greater: std::strong_ordering::less;}
};
#endifint main(void)
{Person p1{"zhangsan", 11.1};Person p2{"zhangsan", 22.2};std::cout << (p1 <= p2) << std::endl;}

对于空类,默认操作符比较所有对象为相等:==、<= 和>= 生成true,!=、< 和> 生成false,而
<=> 生成std::strong_ordering::equal。

 默认<=> 操作符实现默认== 操作符
当操作符<=> 成员定义为默认值时,若没有提供默认操作符==,则根据定义也定义相应的操
作符== 成员,可采用相应的方式(可见性、虚拟、属性、需求等)。例如:

Compatibility issues with the comparison operators 

 

//C++17 OK
#include <iostream>class MyType{
public:MyType(int i)    // implicit constructor from int:: value{i}{}bool operator==(const MyType& rhs) const { return value == rhs.value; }
private:int value;
};bool operator==(int i, const MyType& t)
{return t == i;// OK with C++17 ==>call: t.operator==(MyType(i));
}int main()
{MyType x = 42;if (42 == x){std::cout << "'42 == MyType{42}' works\n";}
}

Unfortunately, this code no longer works in C++20. It results in an endless recursion.

This is because inside the global function, the expression can also call the global operator==() itself. Because the compiler also tries to rewrite the call as

bool operator==(int i, const MyType& t)

{

    return t == i; /* compiler finds #1:   operator==(i,t)  => not need to implicit type coversion

                                                and   #2:   t.operator(MyType{i}) => need to implicit type coversion

                            #1 is better match than #2

                           */

}

Solution :

1. Code only work with C++20: remove the free-standing function

2. Otherwise, you can use an explicit conversion:

bool operator==(int i, const MyType& t)

{

        return t == MyType{i}; // OK until C++17 and with C++20

}

// test log:
#include <iostream>
class MyType{
public:MyType(int i)    // implicit constructor from int:: value{i}{}bool operator==(const MyType& rhs) const {std::cout << "operator== member" << std::endl;return value == rhs.value;}private:int value;
};bool operator==(int i, const MyType& t){std::cout << "operator == free function" << std::endl;return t == i;// OK with C++17 ==>call: t.operator==(MyType(i));
}int main(){MyType x = 42;if (42 == x){std::cout << "'42 == MyType{42}' works\n";}
}

 

相关文章:

Operator <=> (spaceship operator)

operator <>动机 在C20以前定义比较运算符&#xff1a;其他比较运算符基于<和实现 struct Type {int value;// 相等运算符friend bool operator(const Type& a, const Type& b) {return a.value b.value;}// 不等运算符friend bool operator!(const Type&a…...

队列的简单例题

题目如下 模拟队列 首先你要明白队列的话 只有队尾才能进行新增&#xff0c;也就是入队 只有队首才能出队&#xff0c;也就是删除 队首队尾指针一开始默认都是0 相当于队列中一开始是有一个元素的就是 0的位置 队首指针head0 队尾指针tail0 1.入队也就是队尾要先赋值&#xf…...

Calibre-Web-Automated:打造你的私人图书馆

有没有小伙伴在工作、学习或生活中喜欢保存一些书籍或PDF文件&#xff0c;结果过一段时间想找的时候却怎么也找不到&#xff0c;最后只能无奈放弃&#xff1f;你是否已经厌倦了手动管理电子书的繁琐&#xff1f;是否梦想拥有一个私人图书馆&#xff0c;随时随地都能轻松访问自己…...

第27周JavaSpringboot 前后端联调

电商前后端联调课程笔记 一、项目启动与环境搭建 1.1 项目启动 在学习电商项目的前后端联调之前&#xff0c;需要先掌握如何启动项目。项目启动是整个开发流程的基础&#xff0c;只有成功启动项目&#xff0c;才能进行后续的开发与调试工作。 1.1.1 环境安装 环境安装是项…...

【实战ES】实战 Elasticsearch:快速上手与深度实践-8.2.1AWS OpenSearch无服务器方案

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 8.2.1AWS OpenSearch 无服务器方案深度解析与实践指南1. Serverless架构的核心价值与行业趋势1.1 传统Elasticsearch集群的运维挑战1.2 Serverless技术演进路线技术特性对比…...

鸿蒙开发者社区资源的重要性

鸿蒙系统&#xff0c;作为华为公司自主研发的操作系统&#xff0c;旨在为各类智能设备提供统一的平台。它不仅支持手机、平板电脑等移动设备&#xff0c;还涵盖了物联网&#xff08;IoT&#xff09;设备和其他智能家居产品。鸿蒙系统的开发环境和工具链对于开发者来说至关重要&…...

【QT】事件系统入门——QEvent 基础与示例

一、事件介绍 事件是 应用程序内部或者外部产生的事情或者动作的统称 在 Qt 中使用一个对象来表示一个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口需要重新绘制的时候&…...

⚡️Jolt -- 通过JSON配置来处理复杂数据转换的工具

简介&#xff1a;一个能够通过JSON配置&#xff08;特定的语法&#xff09;来处理复杂数据转换的工具。 比如将API响应转换为内部系统所需的格式&#xff0c;或者处理来自不同来源的数据结构差异。例如&#xff0c;将嵌套的JSON结构扁平化&#xff0c;或者重命名字段&#xff0…...

2025-03-13 禅修-错误的做法

摘要: 2025-03-13 禅修-错误的做法 禅修-错误的做法 我们今天的课程是这个禅修防误。主要是有一些我们所明令禁止的。在整个禅修过程中&#xff0c;会对我们禅修出现一些弊端的这部分&#xff0c;我们会给大家介绍。第一&#xff0c;在禅修中要防止自由联想&#xff0c;防止幻…...

uni-app学习笔记——自定义模板

一、流程 1.这是一个硬性的流程&#xff0c;只要按照如此程序化就可以实现 二、步骤 1.第一步 2.第二步 3.第三步 4.每一次新建页面&#xff0c;都如第二步一样&#xff1b;可以选择自定义的模版&#xff08;vue3Setup——这是我自己的模版&#xff09;&#xff0c;第二步的…...

【医院绩效管理专题】8.医院绩效数据的收集与整理方法:洞察现状,引领未来

医院成本核算、绩效管理、运营统计、内部控制、管理会计专题索引 一、引言 在当今医疗行业竞争日益激烈的背景下,医院绩效管理已成为提升医疗服务质量、优化运营效率、增强综合竞争力的关键因素。而绩效数据的收集与整理作为绩效管理的基础环节,其科学性、准确性和完整性直…...

麒麟系统如何安装Anaconda

在银河麒麟操作系统&#xff08;Kylin OS&#xff09;中安装 Anaconda 的步骤相对简单&#xff0c;以下是基于搜索结果整理的详细安装指南&#xff1a; 步骤 1&#xff1a;下载 Anaconda 安装脚本 打开浏览器&#xff0c;访问 Anaconda 官方下载页面。选择适合 Linux 系统的安…...

Linux网络套接字编程——UDP服务器

Linux网络套接字编程——创建并绑定-CSDN博客 前面已经介绍了网络套接字的创建和绑定&#xff0c;这篇文章会通过UDP套接字实现一个UDP服务器。 先介绍将使用的接口。 recvfrom ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr,…...

deepseek+kimi做ppt教程记录

1.首先注册deepseek和kimi deepseek官网&#xff1a;https://chat.deepseek.com/ kimi官网&#xff1a;https://kimi.moonshot.cn/ 以下以一篇工作总结报告为例 2.使用deepseek生成ppt大纲 让deepseek生成kimi生成ppt所需要的内容时&#xff0c;需要注意提示词内容&#xff0c;…...

Cursor 终极使用指南:从零开始走向AI编程

Cursor 终极使用指南&#xff1a;从零开始走向AI编程 问什么是cursor? mindmaproot(Cursor核心功能)智能编码代码生成自动补全错误修复项目管理多窗口布局版本控制终端集成个性设置主题定制快捷键配置插件扩展AI协作对话编程知识检索文档生成前些天发现了一个巨牛的人工智能学…...

TiDB 观测性解读(一)丨索引观测:快速识别无用索引与低效索

导读 可观测性已经成为分布式系统成功运行的关键组成部分。如何借助多样、全面的数据&#xff0c;让架构师更简单、高效地定位问题、分析问题、解决问题&#xff0c;已经成为业内的一个技术焦点。本系列文章将深入解读 TiDB 的关键参数&#xff0c;帮助大家更好地观测系统的状…...

批量将 Excel 文档中的图片提取到文件夹

前面我们介绍过如何批量删除 Excel 文档中的所有图片或者指定的图片&#xff0c;其中就需要用到批量提取 Excel 文档中图片的操作。我们如何才能够将 Excel 文档中的图片快速的提取出来呢&#xff1f;其实单个 Excel 文档中的图片提取到文件夹中是有多种方法可以完成的&#xf…...

postgresql 数据库使用

目录 索引 查看索引 创建 删除索引 修改数据库时区 索引 查看索引 select * from pg_indexes where tablenamet_table_data; 或者 select * from pg_statio_all_indexes where relnamet_table_data; 创建 CREATE INDEX ix_table_data_time ON t_table_data (id, crea…...

怎样进行相关论文的调研——How to conduct research on relevant papers?

怎样进行相关论文的调研 写在前面1.打开Web of Science2.检索同类表达3.构建“检索式”什么是“检索式” 参考内容 写在前面 偶然间刷到一篇知乎文章&#xff0c;顺着文章的推荐看了钟澄老师的科研论和在B站上的教学视频&#xff0c;深入了解后发现读文章还有这么多讲究&#…...

蓝桥杯备赛-基础练习 day1

1、闰年判断 问题描述 给定一个年份&#xff0c;判断这一年是不是闰年。 当以下情况之一满足时&#xff0c;这一年是闰年:1.年份是4的倍数而不是100的倍数 2&#xff0e;年份是400的倍数。 其他的年份都不是闰年。 输入格式 输入包含一个…...

本地算力部署大模型详细流程(一)

1、版本选择 本地部署就是自己部署deepseek模型&#xff0c;使用本地的算力。 主要瓶颈&#xff1a;内存显存的大小。特点&#xff1a;此方案不用联网。适合&#xff1a;有数据隐私方面担忧的或者保密单位根本就不能上网的。 2、部署过程 比较流行的是使用ollama&#xff1a;ht…...

便利店商品推荐数字大屏:基于python和streamlit

基于python和streamlit实现的便利店商品推荐大屏&#xff0c;针对选择困难症消费者。 import streamlit as st import pandas as pd import numpy as np import altair as alt from datetime import datetime, timedelta import time# 模拟数据生成 def generate_data():np.ra…...

机器视觉工程师红外相机的选择:红外长波工业相机和短波红外工业相机玄机大总结

红外长波(LWIR)和短波(SWIR)工业相机在原理、应用场景和技术特点上有显著差异。以下是它们的对比分析: 1. 波长范围与成像原理 2. 技术特点 3. 典型应用场景 4. 优缺点对比 LWIR优势: 无需光照,适用于完全黑暗环境。 直接反映物体温度分布。 对烟雾、灰尘穿透能力强。…...

AI重构SEO关键词布局

内容概要 在搜索引擎优化&#xff08;SEO&#xff09;领域&#xff0c;AI技术的深度应用正在颠覆传统关键词布局逻辑。通过机器学习算法与语义分析模型&#xff0c;智能系统能够实时解析海量搜索数据&#xff0c;构建动态词库并精准捕捉用户意图。相较于依赖人工经验的关键词筛…...

c语言经典基础编程题

c语言经典基础编程题 一、输出输出1.1温度输出1.2排齐数据1.3进制转换 二、选择分支2.1求最大值2.2成绩评定2.3分段函数求值2.4 利润计算2.5判断闰年2.6二次方程根 三、循环结构3.1倒数求和3.2最大数3.3判断素数3.4判断完全数3.5打印菱形&#x1f680;&#x1f680;&#x1f68…...

【每日学点HarmonyOS Next知识】防截屏、作用域问题、观察器问题、对话框关闭、判断对象包含某个字段

1、HarmonyOS 防截屏功能如何实现&#xff1f; 防截屏功能如何实现 参考demo&#xff1a; aboutToDisappear(): void {let windowClass: window.Window | undefined undefined;window.getLastWindow(getContext(this)).then((win) > {this.window win }) window.getLas…...

linux操作系统实战

第一题 创建根目录结构中的所有的普通文件 [rootlocalhost ~]# cd /[rootlocalhost /]# mkdir /text[rootlocalhost /]# cd /text[rootlocalhost text]# mkdir /text/boot /text/root /text/home /text/bin /text/sbin /text/lib /text/lib64 /text/usr /text/opt /text/etc /…...

MKS HA-MFV:半导体制造中的高精度流量验证技术解析

引言 在半导体先进制程&#xff08;如3nm节点&#xff09;中&#xff0c;工艺气体流量的精准控制直接决定刻蚀、沉积等关键步骤的均匀性和良率。MKS Instruments推出的 HA-MFV&#xff08;High Accuracy Mass Flow Verifier&#xff09; 通过创新设计解决了传统流量验证技术的…...

图论part2|200. 岛屿数量、695. 岛屿的最大面积

200、岛屿数量 &#x1f517;&#xff1a;200. 岛屿数量 - 力扣&#xff08;LeetCode&#xff09;思路&#xff1a; 1. 深度优先算法 二叉树中dfs要素&#xff1a;1、访问左右相邻子节点 2、判断base case&#xff08;终止条件&#xff09;参考二叉树中的dfs看网格问题1. 网格…...

小白学Agent技术[5](Agent框架)

文章目录 Agent框架Single Agent框架BabyAGIAutoGPTHuggingGPTHuggingGPT工作原理说明GPT-EngineerAppAgentOS-Copilot Multi-Agent框架斯坦福虚拟小镇TaskWeaverMetaGPT微软UFOAgentScope现状 常见Agent项目比较概述技术规格和能力实际应用案例开发体验比较ChatChain模式 Agen…...

SpringBoot为什么流行以及能解决什么问题?

Spring Boot 之所以流行&#xff0c;主要是因为它极大地简化了 Spring 应用的开发&#xff0c;提供了一种开箱即用的体验&#xff0c;使开发者能够快速构建独立运行的、生产级的 Spring 应用。 Spring Boot 为什么流行&#xff1f; 简化配置 传统 Spring 需要大量 XML 或 Java…...

MySQL -- 数据类型

1、数据库的基础数据类型 TINYINT INT BIGINT FLOAT DECIMAL CHAR VARCHAR TEXT BLOB DATE DATETIME TIMESTAMP SET ENUM 2、不同数据类型区别以及作用 1、数值类型 1.1 整数类型 1.1.1 TINYINT 这里我们以TINYINT这个类型为例&#xff0c;解释一下在mysql中…...

TypeScript 中 interface 与 type的使用注意事项 及区别详细介绍

interfact 与 type 的区别及使用方法 一、 interfact 与 type主要区别 二、 interfact 与 type具体用法 1. 定义对象类型 interface 的典型用法&#xff1a; interface Person {name: string;age: number;greet(): void; }type 的等效定义&#xff1a; type Person {name…...

使用位运算如何找到数组中只出现一次的数?

题目链接&#xff1a;137. 只出现一次的数字 II - 力扣&#xff08;LeetCode&#xff09; 算法解析 位运算是用于二进制的运算符号。而对于多次出现的数字&#xff0c;其二进制都是一模一样的&#xff0c;这里是3次重复的出现是数字。由此我们可以想到&#xff0c;如果我们由低…...

复变函数摘记1

复变函数摘记1 1. 基本概念1.1 复数、复变函数1.2 复变函数的极限、连续性1.3 复变函数的导数、微分1.4 解析函数、柯西-黎曼方程 2. 复变函数的积分2.1 复变函数的曲线积分2.2 柯西-古萨基本定理、复合闭路定理2.3 复变函数的不定积分2.4 柯西积分公式、高阶导数 \quad 本文摘…...

(2025|ICLR|厦大华为,LoSA,基于表示互信息的动态层级稀疏率,基于重构误差的秩分配)LLM 的动态低秩稀疏自适应

Dynamic Low-Rank Sparse Adaptation for Large Language Models 目录 1. 引言 1.1 关键词 2. 方法 2.1 预备知识 2.2 层级稀疏率确定 2.3 稀疏感知的秩分配 2.4 动态稀疏与适配 3. 实验 3.1 实验设置 3.2 语言建模 3.3 零样本任务 3.4 N:M 稀疏性 3.5 消融实验 …...

暨南大学智科人工智能复试模拟

本人初试统招线以外&#xff0c;复试逆袭上岸&#xff01;&#xff01;&#xff01;复试中的笔试和面试尤为重要&#xff0c;笔试固然重要但是面试的不确定性更强。另外&#xff0c;很多同学在复试之前可能都没有完整的走过一遍复试面试的流程&#xff0c;这里建议大家最好是能…...

编译器视角下的 C++ 异常:探究 throw 与 catch 的编译原理

目录 0.写在前面 1.C异常概念 异常的定义&#xff1a; 异常处理的基本组成部分&#xff1a; 1. throw表达式 2. try块 3. catch块 2. 异常的使用 异常的抛出和匹配原则&#xff1a; 在函数调用链中异常栈展开匹配原则&#xff1a; 3.异常的重新抛出 4.异常安全 异…...

测试淘宝评论接口返回数据的详细说明

在电商数据分析、用户体验优化和竞品分析中&#xff0c;获取商品评论数据是一项重要的功能。淘宝开放平台提供了商品评论的 API 接口&#xff0c;允许开发者通过合法的方式获取商品的用户评论数据。本文将详细介绍如何测试淘宝评论接口的返回数据&#xff0c;包括接口调用步骤、…...

【微知】plantuml在泳道图中如何将几个步骤放入一个框中?(group “sub框1“; end !! “sub框1“)

背景 将几个步骤放在一起画个框&#xff0c;分区方便 命令 用法&#xff1a; group 和 end 关键字 用法&#xff1a; group "sub框1"User -> User: 模板渲染User -> User: 返回 HTMLend !! "sub框1" 这里!!是注释实操 修改前&#xff1a; 修改…...

深入解析 React 最新特性:革新、应用与最佳实践

深入解析 React 最新特性&#xff1a;革新、应用与最佳实践 1. 引言 React 作为前端开发的核心技术之一&#xff0c;近年来不断推出 新的 API 和优化机制&#xff0c;从 Concurrent Rendering&#xff08;并发模式&#xff09; 到 Server Components&#xff08;服务器组件&a…...

C语言之数据结构:理解什么是数据结构和算法(启航)

引言 启航篇&#xff0c;理解什么是数据结构和算法 在 C 语言编程领域&#xff0c;数据结构和算法是两个核心且紧密相关的概念 一、数据结构 定义 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合&#xff08;比如数组&#xff09;&#xff0c;它是组织和存储数…...

【21】单片机编程核心技巧:if语句逻辑与真假判断

【21】单片机编程核心技巧&#xff1a;if语句逻辑与真假判断 七律 条件分野 if语句判真假&#xff0c;括号条件定乾坤。 非零为真零为假&#xff0c;大括号内藏玄门。 省略虽简风险在&#xff0c;代码规范护本根。 单片逻辑由心控&#xff0c;条件分支自成文。 注释&#xf…...

hackme靶机通关攻略

第一步&#xff1a;确定靶机IP 第二步&#xff1a;使用御剑后台扫描工具扫描敏感文件 第三步&#xff1a;访问register.php注册登录&#xff0c;进入welcome.php页面 第四步&#xff1a;访问一个不存在的页面&#xff0c;确定网站使用的中间件是Apache&#xff08;无用&#xf…...

网络安全演练有哪些形式

OPENVAS使用 1、确定指定IP是否能ping通 2、创建扫描目标 3、创建扫描任务&#xff08;scan management →newtask&#xff09; 4、开始任务start 5、查看扫描细节 6、查看扫描结果&#xff0c;包含漏洞详细信息&#xff0c;亦可到处PDF文件 7、导出扫描结果报告 8、为…...

PE,ELF,COFF

本文来自 (1)腾讯元宝 (2)程序员的自我修养 PE&#xff08;Portable Executable&#xff09;是一种文件格式&#xff0c;主要用于Windows操作系统中的可执行文件&#xff08;如.exe、.dll、.sys等&#xff09;。PE格式是Windows操作系统中标准的可执行文件格式&#xff0c;由…...

sql靶场-时间盲注(第九、十关)保姆级教程

目录 时间盲注&#xff08;第九、十关&#xff09; 1.判断 2.确认时间盲注 2.手工尝试时间盲注 数据库名长度 数据库名字符 表数 表名长度 表名字符 字段数 字段名长度 字段名字符 4.脚本时间盲注注入 5.第十关 时间盲注&#xff08;第九、十关&#xff09; 1.判…...

常见FUZZ姿势与工具实战:从未知目录到备份文件漏洞挖掘

本文仅供学习交流使用&#xff0c;严禁用于非法用途。未经授权&#xff0c;禁止对任何网站或系统进行未授权的测试或攻击。因使用本文所述技术造成的任何后果&#xff0c;由使用者自行承担。请严格遵守《网络安全法》及相关法律法规&#xff01; 目录 本文仅供学习交流使用&am…...

【linux】解决 Linux 系统中 root 用户无法打开图形界面问题

【linux】解决 Linux 系统中 root 用户无法打开图形界面问题 问题描述&#xff1a; 在 Linux 系统中&#xff0c;当我们远程SSH尝试以 root 用户身份运行需要图形界面的应用程序时&#xff0c;可能会遇到以下错误信息&#xff1a; MoTTY X11 proxy: Unsupported authorisati…...

数据库系统概念全面解析

数据库系统可能看起来很抽象&#xff0c;但其实它们就像我们生活中的许多事物一样&#xff0c;有着清晰的结构和规则。让我们通过一些有趣的生活例子来理解这些概念。 一、数据库系统基础 想象一个图书馆&#xff1a; - 数据库管理系统(DBMS) 就像图书馆的管理员 - 数据库(DB…...