C++其他语法..
1.运算符重载
之前有一个案例如下所示 其中我们可以通过add方法将两个点组成一个新的点
class Point {friend Point add(Point, Point);int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}
};
Point add(Point p1, Point p2) {return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
}
int main() {Point p1(10, 20);Point p2(20, 30);Point p3 = add(p1, p2);p3.display();getchar();return 0;
}
但是有一个想法就是 可不可以直接通过加法运算将两个顶点组成新的点 即Point p3 = p1 + p2
答案是可以的 我们可以通过实现operator+来为加法运算增加新功能
以下案例中 我们通过重载方法operator实现了Point对象的加法运算
class Point {friend Point operator+(Point p1, Point p2);int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}
};
Point operator+(Point p1, Point p2) {return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
}
int main() {Point p1(10, 20);Point p2(20, 30);Point p3 = p1 + p2;p3.display();getchar();return 0;
}
其实p1 + p2的本质就是调用了operator+(p1, p2)
我们再来看一下以下这个案例
class Point {friend Point operator+(Point p1, Point p2);int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}
};
Point operator+(Point p1, Point p2) {return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
}
int main() {Point p1(10, 20);Point p2(20, 30);Point p3(30, 40);Point p4 = p1 + p2 + p3;p4.display();getchar();return 0;
}
我们应该可以知道p1 + p2 + p3的本质其实就是调用了两次operator+
我们可以对上述operator+方法进行优化 具体改写成
修改原因:1.对象类型做参数时 可能会产生不必要的中间对象 所以尽量使用引用/指针来避免
2.参数用const修饰可以使得参数接受范围更大 因为他可以接收const和非const参数 而非const形参显然只能接收非const实参
基于以上两点原因 有了以下优化代码
Point operator+(const Point& p1, const Point& p2) {return Point(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
}
说到这里 我们应该就可以明白拷贝构造函数形参如此写法的原因了
原因有二:1.如果我们的形参是一个对象类型的话 那么当我们调用拷贝构造函数创建一个新对象时 就会无限次的调用该拷贝构造函数 原因在于将实参赋值给形参就会创建新对象 从而调用拷贝构造函数 调用了之后 又会将实参赋值给形参从而调用构造函数 之后就一直重复这个过程 但当我们将对象类型改成引用类型以后 我们就可以杜绝无限调用的现象
2.如果我们传递的实参是const修饰 那么显然非const形参是无法接收这个实参的 所以必须要将形参设计为const修饰 才能接收更大范围的实参
其实对于运算符重载函数而言 我们还可以进一步优化 将其内置于类内部 变成成员函数 这样做的好处是我们可以不用通过友元函数的声明来实现对类内部私有成员的访问 在类内部的成员函数就可以直接访问类内部的私有成员了
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}Point operator+(const Point& p2) {return Point(m_x + p2.m_x, m_y + p2.m_y);}
};
int main() {Point p1(10, 20);Point p2(20, 30);// 相当于调用了p1对象内部的operator+函数 即p1.operator+(p2)Point p3 = p1 + p2;p3.display();getchar();return 0;
}
模仿以上案例 我们可以自己来实现一下减法运算符重载函数 其中p2 - p1的本质就是调用了p2.operator-(p1)
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}Point operator+(const Point& p2) {return Point(m_x + p2.m_x, m_y + p2.m_y);}Point operator-(const Point& p2) {return Point(m_x - p2.m_x, m_y - p2.m_y);}
};
int main() {Point p1(10, 20);Point p2(20, 30);Point p3 = p2 - p1;p3.display();getchar();return 0;
}
但是呢 有一个潜在的问题 我们知道 对一个临时数据赋值是没有任何意义的 因为他马上就要销毁了 而在赋值到销毁的这段过程中完全是发生在当前语句中 所以压根不能被任何人使用
在c++中 允许对一个表达式进行赋值操作的 也允许对对象之间的运算结果进行赋值操作 但是不允许对常量进行赋值操作
表达式中对象之间的运算结果便是一个临时数据(未用一块内存进行储存) 虽然可以对其赋值 但是没有任何意义 所以我们要杜绝这种赋值行为
我们可以将返回值设置成常量 这样表达式的结果就是一个常量 自然而然是不可以对一个常量进行赋值操作的
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) {return Point(m_x - p2.m_x, m_y - p2.m_y);}
};
int main() {Point p1(10, 20);Point p2(20, 30);(p1 + p2) = Point(40, 50);// errorgetchar();return 0;
}
但是一旦运算符重载函数的返回值修改成了常量 那么之前的三数相加或者三数相减的操作就不被允许了 为什么呢 这是因为const对象只能调用const函数 不能调用非const函数的缘故 所以我们需要将运算符重载函数修改成const修饰的函数
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) {return Point(m_x - p2.m_x, m_y - p2.m_y);}
};
int main() {Point p1(10, 20);Point p2(20, 30);Point p3(30, 40);Point p4 = p1 + p2 + p3;// errorgetchar();return 0;
}
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}
};
int main() {Point p1(10, 20);Point p2(20, 30);Point p3(30, 40);Point p4 = p1 + p2 + p3;// okp4.display();getchar();return 0;
}
除了加法和减法运算 我们还可以实现一下+=运算符的重载函数
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}void operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;}
};
int main() {Point p1(10, 20);Point p2(20, 30);p1 += p2;p1.display();getchar();return 0;
}
但是a += b这个表达式是可以被赋值的 因为表达式的结果是一块内存 所以p1 += p2是可以进行赋值操作的 我们希望可以有+=重载函数有一个返回值 这样由此创建的表达式就可以进行赋值操作了
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}
};
int main() {Point p1(10, 20);Point p2(20, 30);(p1 += p2) = Point(40, 50);p1.display();getchar();return 0;
}
但是 打印的结果不符合我们的预期 因为实际上p1 += p2的结果是一个全新的对象 只不过他拷贝了p1的数据而已 为了防止函数调用完毕局部变量被回收的现象
所以说为了避免中间对象的产生(主要是为了减少内存开销 但是可能会指向一块回收后再次分配的内存)而导致数据的错误 我们需要将返回值改成引用类型的
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}
};
int main() {Point p1(10, 20);Point p2(20, 30);(p1 += p2) = Point(40, 50);p1.display();getchar();return 0;
}
由于+=重载方法中需要修改成员变量 而const函数不能修改 所以+=重载方法是不可以由const修饰的
我们在来看一下==运算符重载函数的实现 但是需要注意的是如果是const对象调用operator ==方法的话 那么该方法只能够是const修饰
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}bool operator==(const Point& p2) const {return ((m_x == p2.m_x) && (m_y == p2.m_y));}
};
int main() {Point p1(10, 20);Point p2(20, 30);cout << (p1 == p2) << endl;getchar();return 0;
}
我们实现一下!=运算符重载函数 但是需要注意的是如果是const对象调用operator!=方法的话 那么该方法只能够是const修饰
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}bool operator==(const Point& p2) const {return ((m_x == p2.m_x) && (m_y == p2.m_y));}bool operator!=(const Point& p2) const {return ((m_x != p2.m_x) || (m_y != p2.m_y));}
};
int main() {Point p1(10, 20);Point p2(20, 30);cout << (p1 != p2) << endl;getchar();return 0;
}
我们实现一下负号运算符重载函数 请注意 负号是不会改变操作数的数值的
既然负号不会改变操作数的数值 那么我们就需要返回一个新建的对象
由于返回值构成的表达式可以被赋值 而赋值操作没有任何意义 所以我们需要禁止赋值 所以用const修饰返回值
如果我们接连使用多次负号 那么就会产生const对象调用的问题 const对象只能够调用const函数 所以我们需要用const修饰函数
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}bool operator==(const Point& p2) {return ((m_x == p2.m_x) && (m_y == p2.m_y));}bool operator!=(const Point& p2) {return ((m_x != p2.m_x) || (m_y != p2.m_y));}const Point operator-() const {return Point(-m_x, -m_y);}
};
int main() {Point p1(10, 20);Point p2(20, 30);Point p3 = (-(-p1));p1.display();p3.display();getchar();return 0;
}
我们在来实现一下自增运算符重载函数
这得分成两类 一类是前缀自增运算符重载函数 一类则是后缀自增运算符重载函数 这两类在写法上有所区分 前者就是默认的写法 而后者则是基于默认写法的基础上在参数列表中加入int
我们先来讲讲前缀自增运算符重载函数
由于前缀自增表达式可以被赋值 所以需要有返回值
再者 为了防止产生中间对象而导致数据错乱 所以我们需要让返回值变成引用类型
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}bool operator==(const Point& p2) {return ((m_x == p2.m_x) && (m_y == p2.m_y));}bool operator!=(const Point& p2) {return ((m_x != p2.m_x) || (m_y != p2.m_y));}const Point operator-() const {return Point(-m_x, -m_y);}Point& operator++() {m_x++;m_y++;return *this;}
};
int main() {Point p1(10, 20);Point p2(20, 30);(++p1) = Point(40, 50);p1.display();getchar();return 0;
}
然后再来讲讲后缀自增运算符重载函数
由于后缀自增表达式可以参与到加法运算中 所以需要返回值Point 但是同时也可以进行赋值运算了
但是由于我的预期是对最新的值进行赋值操作 而不是针对旧值 所以说 我们不能进行赋值操作 所以需要用const修饰返回值
class Point {int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}bool operator==(const Point& p2) {return ((m_x == p2.m_x) && (m_y == p2.m_y));}bool operator!=(const Point& p2) {return ((m_x != p2.m_x) || (m_y != p2.m_y));}const Point operator-() const {return Point(-m_x, -m_y);}Point& operator++() {m_x++;m_y++;return *this;}const Point operator++(int) {Point old(m_x, m_y);m_x++;m_y++;return old;}
};
int main() {Point p1(10, 20);Point p2(20, 30);Point p3 = p2++ + Point(40, 50);p3.display();getchar();return 0;
}
我们再来实现一下左移运算符重载函数
首先左移运算符重载函数不可以写在类内部 因为这样会导致<<左边必须为对象类型 而真实代码中<<左边必须是cout(cout是一个类对象 是ostream类对象 ) 所以需要将重载方法定义为全局方法 但是我们就需要将该方法声明为友元方法 这样才能够访问类内部的私有成员
再者 重载方法需要返回值 因为<<可以连用 并且<<左边必须是cout对象 所以返回值是ostream类型 为了防止中间对象的产生 所以返回值需要为ostream&引用类型 至于说要不要加上const修饰 通过测试基本类型的cout的赋值操作(比如:cout << 1 = cout) 我们可以知道赋值操作是行不通的 所以我们需要将返回值设置为常量 即用const修饰返回值 而且由于返回值是const的缘故 导致形参中cout也必须是const修饰
我说实话 const只能够修饰成员函数 并不能修饰全局函数(const对象只能调用const成员函数 但是对于全局函数来说 有无const没有任何影响)
并且由于C++内置的cout行为所在的方法中形参cout也是非const修饰 基于这一点 我们都不能把返回值设置为const修饰
至于说 左移运算符重载函数内部要不要写死endl 如果你是想要将endl灵活的布局在cout语句中 那么请不要写死 反之可以写死 而且千万不要有这种想法 就是cout << endl;执行的是我们自定义的这个方法 实际上他执行的是C++内置的行为
class Point {friend ostream& operator<<(ostream& cout, const Point& p);int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}bool operator==(const Point& p2) {return ((m_x == p2.m_x) && (m_y == p2.m_y));}bool operator!=(const Point& p2) {return ((m_x != p2.m_x) || (m_y != p2.m_y));}const Point operator-() const {return Point(-m_x, -m_y);}Point& operator++() {m_x++;m_y++;return *this;}const Point operator++(int) {Point old(m_x, m_y);m_x++;m_y++;return old;}
};
ostream& operator<<(ostream& cout, const Point& p) {cout << "(" << p.m_x << ", " << p.m_y << ")";return cout;
}
int main() {Point p1(10, 20);Point p2(20, 30);cout << p1 << p2 << endl;getchar();return 0;
}
最后再来实现一下右移运算符重载函数 同样的 由于成员函数要求>>左边必须是对象类型 而不是istream类型 所以我们得将其声明为全局函数
接着 由于C++中内置的cin的行为所在的函数的形参cin是非const修饰 所以编译器为了让我们统一格式 所以也要求我们自定义的方法中形参的cin必须不被const所修饰 所以也就要求我们函数的返回值不被const修饰
我们也不能用const修饰全局函数
由于我们键入数据的行为相当于对指定变量进行修改 所以我们不能够将形参中的对象类型用const修饰 因为常量是不可以修改的
class Point {friend ostream& operator<<(ostream& cout, const Point& p);friend istream& operator>>(istream& cin, Point& p);int m_x;int m_y;
public:Point(int x, int y) : m_x(x), m_y(y){}void display() {cout << "(" << m_x << ", " << m_y << ")" << endl;}const Point operator+(const Point& p2) const {return Point(m_x + p2.m_x, m_y + p2.m_y);}const Point operator-(const Point& p2) const {return Point(m_x - p2.m_x, m_y - p2.m_y);}Point& operator+=(const Point& p2){m_x += p2.m_x;m_y += p2.m_y;return *this;}bool operator==(const Point& p2) {return ((m_x == p2.m_x) && (m_y == p2.m_y));}bool operator!=(const Point& p2) {return ((m_x != p2.m_x) || (m_y != p2.m_y));}const Point operator-() const {return Point(-m_x, -m_y);}Point& operator++() {m_x++;m_y++;return *this;}const Point operator++(int) {Point old(m_x, m_y);m_x++;m_y++;return old;}
};
ostream& operator<<(ostream& cout, const Point& p) {cout << "(" << p.m_x << ", " << p.m_y << ")";return cout;
}
istream& operator>>(istream& cin, Point& p) {cin >> p.m_x;cin >> p.m_y;return cin;
}
int main() {Point p1(10, 20);Point p2(20, 30);cin >> p1 >> p2;cout << p1 << p2 << endl;getchar();return 0;
}
我们在自定义对象类型的相关运算符的重载函数时 优先考虑成员函数 不行在定义为全局函数
那么为什么对于刚才的左移运算符重载函数和右移运算符重载函数 他们的返回值既然都是非const 那理应可以进行赋值操作 为什么反而不行 这是因为在ostream/istream类中 赋值运算符重载函数是一个私有的函数 不可访问
从这个解答 我们也可以得出一个思路:
之前的对象拷贝操作如果没有自定义拷贝构造函数的话 那么就得对所有的成员进行赋值操作 但是如果不想要对所有的成员赋值的话 那么我们也可以通过拷贝构造函数进行部分成员的赋值 但是如果连拷贝构造函数都没有的话 那么我们也可以在类中自定义一个赋值运算符重载函数已完成部分成员的赋值操作
总结一下 对于以上重载函数的书写 有个大致的思路:
首先我们可以将基本类型的解决方法代入到对象类型的程序流程中
接着我们需要判断是否需要返回值 这取决于我们是否需要连用、赋值或者参与运算符等其他操作
接着需要判断一下返回值是否需要设置为引用类型 如果没有引用类型会使得预期出现偏差的话 那么我们就需要将返回值设计为引用类型
接着如果返回值确定为不可赋值的话 那么显然为常量 所以返回值需要用const修饰
然后函数需不需要用const修饰取决于你是否需要通过const对象去调用成员函数 因为对于const对象而言 他只可以调用const修饰的成员函数 但是对于全局函数 有无const不影响
相关文章:
C++其他语法..
1.运算符重载 之前有一个案例如下所示 其中我们可以通过add方法将两个点组成一个新的点 class Point {friend Point add(Point, Point);int m_x;int m_y; public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(" << m_x <<…...
【Vue3源码学习】— CH2.6 effect.ts:详解
effect.ts:详解 1. 理解activeEffect1.1 定义1.2 通过一个例子来说明这个过程a. 副作用函数的初始化b. 执行副作用函数前c. 访问state.countd. get拦截器中的track调用e. 修改state.count时的set拦截器f. trigger函数中的依赖重新执行 1.3 实战应用1.4 activeEffect…...
C语言:文件操作(一)
目录 前言 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1 文件指针 3.2 文件的打开和关闭 结(一) 前言 本篇文章将介绍C语言的文件操作,在后面的内容讲到:为什么使用文…...
集中进行一系列处理——函数
需要多次执行相同的处理,除了编写循环语句之外,还可以集中起来对它进行定义。 对一系列处理进行定义的做法被称为函数,步骤,子程序。 对函数进行定一后,只需要调用该函数就可以了。如果需要对处理的内容进行修正&…...
git diff
1. 如何将库文件的变化生成到patch中 git diff --binary commit1 commit2 > test.patch 打patch: git apply test.patch 2. 如何消除trailing whitespace 问题 git diff --ignore-space-at-eol commit1 commit2 > test.patch 打patch: git ap…...
新手使用GIT上传本地项目到Github(个人笔记)
亲测下面的文章很有用处。 1. 初次使用git上传代码到github远程仓库 - 知乎 (zhihu.com) 2. 使用Git时出现refusing to merge unrelated histories的解决办法 - 知乎...
结合《人力资源管理系统》的Java基础题
1.编写一个Java方法,接受一个整数数组作为参数,返回该数组中工资高于平均工资的员工数量。假设数组中的每个元素都代表一个员工的工资。 2.设计一个Java方法,接受一个字符串数组和一个关键字作为参数,返回包含该关键字的姓名的员…...
PostgreSQL备份还原数据库
1.切换PostgreSQL bin目录 配置Postgresql环境变量后可以不用切换 pg_dump 、psql都在postgresql bin目录下,所以需要切换到bin目录执行命令 2.备份数据库 方式一 语法 pg_dump -h <ip> -U <pg_username> -p <port> -d <databaseName>…...
实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用
实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用 在数据库管理中,读写分离是一种常见的性能优化方法,它通过将读操作和写操作分发到不同的服务器或数据库实例上,来减轻单个数据库的负载&#x…...
pytest中文使用文档----10skip和xfail标记
1. 跳过测试用例的执行 1.1. pytest.mark.skip装饰器1.2. pytest.skip方法1.3. pytest.mark.skipif装饰器1.4. pytest.importorskip方法1.5. 跳过测试类1.6. 跳过测试模块1.7. 跳过指定文件或目录1.8. 总结 2. 标记用例为预期失败的 2.1. 去使能xfail标记 3. 结合pytest.param方…...
【Spring MVC】快速学习使用Spring MVC的注解及三层架构
💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:【Spring MVC】快速学习使用Spring MVC的注解及三层架构 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 Spring Web MVC一: 什么是Spring Web MVC࿱…...
Python(乱学)
字典在转化为其他类型时,会出现是否舍弃value的操作,只有在转化为字符串的时候才不会舍弃value 注释的快捷键是ctrl/ 字符串无法与整数,浮点数,等用加号完成拼接 5不入??? 还有一种格式化的方法…...
OpenHarmony实战:轻量级系统之子系统移植概述
OpenHarmony系统功能按照“系统 > 子系统 > 部件”逐级展开,支持根据实际需求裁剪某些非必要的部件,本文以部分子系统、部件为例进行介绍。若想使用OpenHarmony系统的能力,需要对相应子系统进行适配。 OpenHarmony芯片适配常见子系统列…...
Neo4j基础知识
图数据库简介 图数据库是基于数学里图论的思想和算法而实现的高效处理复杂关系网络的新型数据库系统。它善于高效处理大量的、复杂的、互连的、多变的数据。其计算效率远远高于传统的关系型数据库。 在图形数据库当中,每个节点代表一个对象,节点之间的…...
HTTP/1.1 特性(计算机网络)
HTTP/1.1 的优点有哪些? 「简单、灵活和易于扩展、应用广泛和跨平台」 1. 简单 HTTP 基本的报文格式就是 header body,头部信息也是 key-value 简单文本的形式,易于理解。 2. 灵活和易于扩展 HTTP 协议里的各类请求方法、URI/URL、状态码…...
每日一题————P5725 【深基4.习8】求三角形
题目: 题目乍一看非常的简单,属于初学者都会的问题——————————但是实际上呢,有一些小小的坑在里面。 就是三角形的打印。 平常我们在写代码的时候,遇到打印三角形的题,一般简简单单两个for循环搞定 #inclu…...
第三题:时间加法
题目描述 现在时间是 a 点 b 分,请问 t 分钟后,是几点几分? 输入描述 输入的第一行包含一个整数 a。 第二行包含一个整数 b。 第三行包含一个整数 t。 其中,0≤a≤23,0≤b≤59,0≤t, 分钟后还是在当天。 输出描…...
【RAG】内部外挂知识库搭建-本地GPT
大半年的项目告一段落了,现在自己找找感兴趣的东西学习下,看看可不可以搞出个效果不错的local GPT,自研下大模型吧 RAG是什么? 检索增强生成(RAG)是指对大型语言模型输出进行优化,使其能够在生成响应之前引用训练数据来…...
MySQL——锁
全局锁 全局锁是一种数据库锁定机制,它可以锁定整个数据库,阻止其他会话对数据库的读写操作。在MySQL中,全局锁定可以使用FLUSH TABLES WITH READ LOCK命令来实现。执行这个命令后,MySQL将获取一个全局读锁,直到当前会…...
C++(12): std::mutex及其高级变种的使用
1. 简述 在多线程或其他许多场景下,同时对一个变量或一段资源进行读写操作是一个比较常见的过程,保证数据的一致性和防止竞态条件至关重要。 C的标准库中为我们提供了使用的互斥及锁对象,帮助我们实现资源的互斥操作。 2. std::mutex及其衍…...
基于ROS软路由的百元硬件升级方案实现突破千兆宽带
前言 很多用户得利于FTTR光网络不断推广,家用宽带带宽已经实现千兆速率的突破。而现在很多ISP运营商已经在多个城市率先推出2000M光宽带。这种情况下,要想将自家宽带的带宽能够充分发挥利用,就需要对原有的千兆设备进行升级来满足突破千兆的…...
OpenHarmony实战开发-分布式关系型数据库
介绍 本示例使用ohos.data.relationalStore 接口和ohos.distributedDeviceManager 接口展示了在eTS中分布式关系型数据库的使用,在增、删、改、查的基本操作外,还包括分布式数据库的数据同步同能。 效果预览 使用说明: 1.启动应用后点击“”按钮可以添…...
图片标注编辑平台搭建系列教程(6)——fabric渲染原理
原理 fabric的渲染步骤大致如下: 渲染前都设置背景图然后调用ctx.save(),存储画布的绘制状态参数然后调用每个object自身的渲染方法最后调用ctx.restore(),恢复画布的保存状态后处理,例如控制框的渲染等 值得注意的是࿰…...
Qt中QIcon图标设置(标题、菜单栏、工具栏、状态栏图标)
1 exe程序图标概述 在 Windows 操作系统中,程序图标一般会涉及三个地方; (1) 可执行程序(以及对应的快捷方式)的图标 (2) 程序界面标题栏图标 (3)程序在任务…...
C语言程序10题
第101题 (10.0分) 难度:易 第2章 /*------------------------------------------------------- 【程序填空】 --------------------------------------------------------- 功能:计算平均成绩并统计90分以上人数。 --…...
定时器-间歇函数
1.开启定时器 setInterval(function (){console.log(一秒执行一次)},1000) function fn(){console.log(一秒执行一次) } setInterval(fn,1000) //调用有名的函数,只写函数名 1.函数名字不需要加小括号 2.定时器返回是一个id数字 每个定时器的序号是不一样的 2.关…...
Ajax-XMLHttpRequest基本使用
一、Ajax的原理 就是XMLHttpRequest对象。 二、为什么学习XHR? 有更多与服务器数据通信方式,了解Ajax内部。 三、XHR使用步骤 1.创建XHR对象 2.调用open方法,设置url和请求方法 3.监听loadend事件,接受结果 4.调用send方法…...
门控循环单元(GRU)
概述 门控循环单元(Gated Recurrent Unit, GRU)由Junyoung Chung等人于2014年提出,原论文为《Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling》。GRU是循环神经网络(Recurrent Neural Network, …...
789. 数的范围 (二分学习)左端大右,右端小左
题目链接https://www.acwing.com/file_system/file/content/whole/index/content/4317/ 当求左端点时,条件是a【mid】大于等于x,并把右端点缩小。 当求右端点时,条件是a【mid】小于等于x,并把左端点扩大。 1.确定一个区间&…...
docker logs 查找日志常用命令
docker logs 是什么 docker logs 是 Docker 命令行工具提供的一个命令,用于查看容器的日志输出。它可以显示容器在运行过程中生成的标准输出(stdout)和标准错误输出(stderr),帮助用户诊断容器的行为和排查…...
德州网页制作/网站seo优化服务
UWB室内高精度定位smarteye server 服务器插件安装使用说明 配置文件goeverywhere.conf修改 Port:监听端口,默认9850 Pos_rate: 2 转发速率(单个设备2秒转发一次) 关于数据库db配置 默认使用的是smarteye服务器自带的5.7mysql…...
济南网站建设公司有哪些/百度seo快速见效方法
OpenVAS漏洞扫描基础教程之创建用户 OpenVAS管理服务 默认情况下,OpenVAS服务仅创建了一个名为admin的用户,而且是管理员用户(拥有最高的权限)。如果想要其它客户端登陆的话,不可能都以管理员身份访问,否则…...
网站设计合同范本/2023年九月份新闻
报名号姓名生源省市专业191033522000094蔡礼阳广东省综合评价-(101)电子与计算机工程(中外合作办学)191033522000480曹淞广东省综合评价-(101)电子与计算机工程(中外合作办学)191033522000684曾成广东省综合评价-(101)电子与计算机工程(中外合作办学)191033522000350曾维翰广东…...
学前心理学课程建设网站/做推广的都是怎么推
这个网站是真免费的那种,不是打着免费的旗号让你付费的套路。 我准备更换公司的bug管理系统,找了半天,找到这个网站最符合我的心意,流程简洁,用起来方便,速度快。 有兴趣的去看看吧: buginfo…...
html5 网站开发工具/网上营销模式
实现一个form1窗体打开form2窗体,当点击form2窗体的按钮时,将form2的文本框中的值改变到form1的文本框中 这是实现的效果: --------------->-----------> 1、这是form1的代码 2、这是form2的代码 转载于:https://www.cnblogs.com/zhudezhiwansui/p/6397801.html...
html 企业网站模板/在线网站流量查询
有没有遇到过,导航UITableView,在push,back回来之后,当前cell仍然是选中的状态。当然,解决办法简单,添加一句[tableView deselectRowAtIndexPath:indexPath animated:YES]即可。令人纠结的时,在…...