C++之运算符重载

1、运算符重载

//Complex.h
#ifndef _COMPLEX_H_
#define _COMPLEX_H_

class Complex
{
public:
    Complex(int real_, int imag_);
    Complex();
    ~Complex();

    Complex& Add(const Complex& other);    
    void Display() const;
    Complex operator+(const Complex& other);

private:
    int real_;
    int imag_;
};
#endif // _COMPLEX_H_

// Complex.cpp
#include "Complex.h"
#include <iostream>
using namespace std;

Complex::Complex(int real, int imag) : real_(real), imag_(imag)
{

}

Complex::Complex()
{

}

Complex::~Complex()
{

}

Complex& Complex::Add(const Complex& other)
{
    real_ += other.real_;
    imag_ += other.imag_;

    return *this; // 因为是引用,所以返回的时候不会调用拷贝构造函数
}

void Complex::Display() const
{
    cout << real_ << "+" << imag_ << endl;
}

Complex Complex::operator+(const Complex& other)
{
    int r = real_ + other.real_;
    int i = imag_ + other.imag_;

    return Complex(r, i);
}


// main.cpp
#include "Complex.h"

int main(void)
{
    Complex c1(3, 5);
    Complex c2(4, 6);
    //c1.Add(c2);  // 但是这样就修改到了c1对象,我们希望是Complex c3 = c1 + c2;这个时候我们就需要运算符的重载
    //c1.Display();

    Complex c3 = c1 + c2;  // 这边其实就是函数调用,相当于c1.operator(c2);
    // Complex c3 = c1.operator(c2);
    c1.Display();
    c2.Display();
    c3.Display();
    return 0;
}

其实运算符的重载,在这边也就是成员函数的重载。

2、非成员函数重载(友元的方式重载)

在vs2008中友元函数的运算符重载能和成员函数的运算符重载共存,有些编译器不行。如果共存,那么优先调用成员函数的运算符重载。

//Complex.h
#ifndef _COMPLEX_H_
#define _COMPLEX_H_

class Complex
{
public:
    Complex(int real_, int imag_);
    Complex();
    ~Complex();

    Complex& Add(const Complex& other);    
    void Display() const;
    Complex operator+(const Complex& other);
    friend Complex operator+(const Complex& c1, const Complex& c2);

private:
    int real_;
    int imag_;
};
#endif // _COMPLEX_H_

// Complex.cpp
#include "Complex.h"
#include <iostream>
using namespace std;

Complex::Complex(int real, int imag) : real_(real), imag_(imag)
{

}

Complex::Complex()
{

}

Complex::~Complex()
{

}

Complex& Complex::Add(const Complex& other)
{
    real_ += other.real_;
    imag_ += other.imag_;

    return *this; // 因为是引用,所以返回的时候不会调用拷贝构造函数
}

void Complex::Display() const
{
    cout << real_ << "+" << imag_ << endl;
}

Complex Complex::operator+(const Complex& other)
{
    int r = real_ + other.real_;
    int i = imag_ + other.imag_;

    return Complex(r, i);
}

Complex operator+(const Complex& c1, const Complex& c2)
{
    int r = c1.real_ + c2.real_;
    int i = c1.imag_ + c2.imag_;

    return Complex(r, i);
}


// main.cpp
#include "Complex.h"

int main(void)
{
    Complex c1(3, 5);
    Complex c2(4, 6);
    //c1.Add(c2);  // 但是这样就修改到了c1对象,我们希望是Complex c3 = c1 + c2;这个时候我们就需要运算符的重载
    //c1.Display();

    Complex c3 = c1 + c2;  // 这边其实就是函数调用,相当于c1.operator(c2);
    // Complex c3 = c1.operator(c2);
    c1.Display();
    c2.Display();
    c3.Display();
    return 0;
}

3、运算符重载的规则

不能重载的运算符:因为如果开放了这些运算符的重载,那么语法就会变得混乱不可控制。

4、++运算符重载

推荐用成员函数进行重载,因为友元重载是全局的。

// Integer.h
#ifndef _INTEGER_H
#define _INTEGER_H

class Integer
{
public:
    Integer (int n);
    ~Integer();

    void Display();

    Integer& operator++();  // 前置++成员函数重载
    //friend Integer& operator++(Integer &i);  // 前置++友元重载
    
    // 友元不能共存

    // 后置中的参数int i没什么用,只是为了区分是否是前置还是后置
    Integer operator++(int i);  // 后置++成员函数重载
    //friend Integer& operator++(Integer &i, int i);  // 前置++友元重载
private:
    int n_;
};

#endif //_INTEGER_H


// Integer.cpp
#include "Integer.h"
#include <iostream>
using namespace std;

Integer::Integer(int n) : n_(n)
{}

Integer::~Integer()
{}

void Integer::Display()
{
    cout << "n_ = " << n_ << endl;
}

//Integer& Integer::operator++()
//{
//    cout << "Integer& Integer::operator++()" << endl;
//    ++n_;
//    return *this;
//}

Integer& operator++(Integer &i)
{
    cout << "Integer& operator++(Integer &i)" << endl;
    ++i.n_;
    return i;  // 因为返回的是引用不是对象,所以不会调用拷贝构造函数
}

//Integer Integer::operator++(int i)
//{
//    cout << "Integer& Integer::operator++(int i)" << endl;
//    //n++,
//    Integer tmp(n_);
//    n_++;
//    return tmp;
//}

Integer& operator++(Integer &i, int j)
{
    cout << "Integer& operator++(Integer &i, int i)" << endl;
    //n++,
    Integer tmp(i.n_);
    i.n_++;
    return tmp;
}
// main.cpp
#include "Integer.h"
#include <iostream>
using namespace std;

int main(void)
{
    Integer n(10);
    n.Display();

    Integer n2 = ++n;
    n.Display();
    n2.Display();

    Integer n3 = n++;
    n.Display();
    n3.Display();

    return 0;
}

5、=赋值运算符重载

//String.h
#ifndef _STRING_H
#define _STRING_H

class String
{
public:
    String(const char* str = "");
    String(const String& other);  // 拷贝构造

    // 当你使用obj1 = obj2的时候,也是浅拷贝,即obj1.str_ = obj2.str_,所以要重载等号运算符,在里面进行深拷贝
    String& operator=(const String& other);
    String& operator=(const char* str);

    void Display() const;
    ~String(void);

private:
    char* AllocAndCopy(const char* str);
    char* str_;
};

#endif //_STRING_H

// String.cpp
#include "String.h"
#include <string.h>
#include <iostream>
using namespace std;

String::String(const char* str)
{
    str_ = AllocAndCopy(str);
}

String::String(const String& other)
{
    str_ = AllocAndCopy(other.str_);
}

String& String::operator=(const String& other)
{
    if (this == &other)
        return *this;

    delete[] str_;
    str_ = AllocAndCopy(other.str_);
    return *this;
}

char* String::AllocAndCopy(const char* str)
{
    int len= strlen(str)+ 1;
    char* newStr= new char[len];
    memset(newStr, 0, len);
    strcpy(newStr, str);

    return newStr;
}
String& String::operator=(const char* str)
{
    delete[] str_;
    str_ = AllocAndCopy(str);
    return *this;
}

void String::Display() const
{
    cout << str_ << endl;
}

String::~String()
{
    delete[] str_;
}

// main.cpp
#include "String.h"
#include <iostream>
using namespace std;

int main(void)
{
    String s1("abc");
    String s2(s1);

    String s3;
    s3 = s1;
    s3.Display();

    s3 = "xxxx";  // 如果没有去重载String& operator=(const char* str);那么先调用转换构造函数String(const char* str)将字符串构造成一个对象,然后再调用String& operator=(const String& other);重载等号运算符进行赋值。
    s3.Display();

    return 0;
}

其实主要是内存释放的问题,因为如果直接=,就是浅拷贝,如果有用malloc的话,释放的时候,一块内存会被释放两次。还有就是写法中调用的问题,s1("abc")调用构造函数;s1(s2)调用拷贝构造,当在构造函数中有开辟空间,则在拷贝构造里面也要开辟空间,避免重复释放。

6、!运算符重载

当字符串是空的,那就是假的,当字符串不为空,那就是真。

//String.h
#ifndef _STRING_H
#define _STRING_H

class String
{
public:
    String(const char* str = "");
    String(const String& other);  // 拷贝构造

    // 当你使用obj1 = obj2的时候,也是浅拷贝,即obj1.str_ = obj2.str_,所以要重载等号运算符,在里面进行深拷贝
    String& operator=(const String& other);
    String& operator=(const char* str);

    bool operator!() const;

    void Display() const;
    ~String(void);

private:
    char* AllocAndCopy(const char* str);
    char* str_;
};

#endif //_STRING_H

// String.cpp
#include "String.h"
#include <string.h>
#include <iostream>
using namespace std;

String::String(const char* str)
{
    str_ = AllocAndCopy(str);
}

String::String(const String& other)
{
    str_ = AllocAndCopy(other.str);
}

String& String::operator=(const String& other)
{
    if (this == other)
        return *this;
    
    delete[] str_;
    str_ = AllocAndCopy(other.str_);
    return *this;
}

char* String::AllocAndCopy(const char* str)
{
    int len= strlen(str)+ 1;
    char* newStr= new char[len];
    menset(newStr, 0, len);
    strcpy(newStr, str);

    return newStr;
}
String& String::operator=(const char* str)
{
    delete[] str_;
    str_ = AllocAndCopy(other.str);
    return *this;
}

bool String::operator!() const
{
    return strlen(str_) != 0;
}

void String::Display() const
{
    cout << str_ << endl;
}

String::~String()
{
    delete[] str_;
}

// main.cpp
#include "String.h"
#include <iostream>
using namespace std;

int main(void)
{
    String s1("abc");
    String s2(s1);

    String s3;
    s3 = s1;
    s3.Display();

    s3 = "xxxx";  // 如果没有去重载String& operator=(const char* str);那么先调用转换构造函数String(const char* str)将字符串构造成一个对象,然后再调用String& operator=(const String& other);重载等号运算符进行赋值。
    s3.Display();

    String s4;
    bool notEmpty;
    notEmpty = !s4;
    cout << notEmpty << endl;

    s4 = "aaaa";
    notEmpty = !s4;
    cout << notEmpty << endl;

    return 0;
}

7、[]运算符重载

//String.h
#ifndef _STRING_H
#define _STRING_H

class String
{
public:
    String(const char* str = "");
    String(const String& other);  // 拷贝构造

    // 当你使用obj1 = obj2的时候,也是浅拷贝,即obj1.str_ = obj2.str_,所以要重载等号运算符,在里面进行深拷贝
    String& operator=(const String& other);
    String& operator=(const char* str);

    bool operator!() const;

    char& operator[](unsigned int index);
    const char& operator[](unsigned int index) const;

    void Display() const;
    ~String(void);

private:
    char* AllocAndCopy(const char* str);
    char* str_;
};

#endif //_STRING_H

// String.cpp
#include "String.h"
#include <string.h>
#include <iostream>
using namespace std;

String::String(const char* str)
{
    str_ = AllocAndCopy(str);
}

String::String(const String& other)
{
    str_ = AllocAndCopy(other.str);
}

String& String::operator=(const String& other)
{
    if (this == other)
        return *this;
    
    delete[] str_;
    str_ = AllocAndCopy(other.str_);
    return *this;
}

char* String::AllocAndCopy(const char* str)
{
    int len= strlen(str)+ 1;
    char* newStr= new char[len];
    menset(newStr, 0, len);
    strcpy(newStr, str);

    return newStr;
}
String& String::operator=(const char* str)
{
    delete[] str_;
    str_ = AllocAndCopy(other.str);
    return *this;
}

bool String::operator!() const
{
    return strlen(str_) != 0;
}

char& String::operator[](unsigned int index)
{
    return str_[index];
    // 因为这里面的代码和const的代码一样,所以最好合并成同一份代码
    // 做法是,non const 版本调用const版本
    return const_cast<char&>(static_cast<const String&>(*this)[index]);
}

const char& String::operator[](unsigned int index) const
{
    return str_[index];
}

void String::Display() const
{
    cout << str_ << endl;
}

String::~String()
{
    delete[] str_;
}

// main.cpp
#include "String.h"
#include <iostream>
using namespace std;

int main(void)
{
    String s1("abcdefg");

    char ch = s1[2];
    cout << ch << endl;  // 输出c

    //为什么[]的返回值是字符串的引用?因为一个函数,如果返回值是引用的话,就可以出现在表达式的左边,这样就能重新赋值。
    s1[2] = 'A';
    s1.Display();  // 输出abAdefg

    const String s2("xyzabc");
    s2[2] = 'M';  // 这边会调用char& operator[](unsigned int index) const这个重载。因为是const对象,所以希望这个操作是不允许的;解决方案:前面加上const,变成const char& operator[](unsigned int index) const;这样的话,这句在编译的时候就会报错
    ch = s2[2];  // 希望这个操作是允许的
    s2.Display();  // 输出xyMabc

    return 0;
}

8、+运算符重载

最好写成友元的方式去重载。

9、+=运算符的重载

// String.h
#ifndef STRING_H
#define STRING_H
class String {
public:
    String(const char* str = "");
    String(const String& other);  // 拷贝构造

    // 当你使用obj1 = obj2的时候,也是浅拷贝,即obj1.str_ = obj2.str_,所以要重载等号运算符,在里面进行深拷贝
    String& operator=(const String& other);
    String& operator=(const char* str);

    bool operator!() const;

    char& operator[](unsigned int index);
    const char& operator[](unsigned int index) const;

    //+运算符重载(最好用友元的方式来重载)
    friend String operator+(const String& s1, const String& s2);
    //+=运算符重载
    String& operator+=(const String& other);

    void Display() const;
    ~String(void);

private:
    static char* AllocAndCopy(const char* str);
    char* str_;
};

#endif //STRING_H
// String.cpp
#include "String.h"
#include "String.h"
#include <string.h>
#include <iostream>
using namespace std;

String::String(const char* str)
{
    str_ = AllocAndCopy(str);
}

String::String(const String& other)
{
    str_ = AllocAndCopy(other.str_);
}

String& String::operator=(const String& other)
{
    if (this == &other)
        return *this;

    delete[] str_;
    str_ = AllocAndCopy(other.str_);
    return *this;
}

char* String::AllocAndCopy(const char* str)
{
    int len= strlen(str)+ 1;
    char* newStr= new char[len];
    memset(newStr, 0, len);
    strcpy(newStr, str);

    return newStr;
}
String& String::operator=(const char* str)
{
    delete[] str_;
    str_ = AllocAndCopy(str);
    return *this;
}

bool String::operator!() const
{
    return strlen(str_) != 0;
}

char& String::operator[](unsigned int index)
{
    return str_[index];
    // 因为这里面的代码和const的代码一样,所以最好合并成同一份代码
    // 做法是,non const 版本调用const版本
    return const_cast<char&>(static_cast<const String&>(*this)[index]);
}

const char& String::operator[](unsigned int index) const
{
    return str_[index];
}

void String::Display() const
{
    cout << str_ << endl;
}

String::~String()
{
    delete[] str_;
}

String operator+(const String& s1, const String& s2)
{
    int len = strlen(s1.str_) + strlen(s2.str_);
    char* newStr = new char[len];
    memset(newStr, 0, len);
    strcpy(newStr, s1.str_);
    strcat(newStr, s2.str_);

    String tmp(newStr);
    delete newStr;
    return tmp;
}

String& String::operator+=(const String& other)
{
    int len = strlen(str_) + strlen(other.str_);
    char* newStr = new char[len];
    memset(newStr, 0, len);
    strcpy(newStr, str_);
    strcat(newStr, other.str_);

    delete[] str_;
    str_ = newStr;
    return *this;
}

// main.cpp
#include <iostream>
#include "String.h"
using namespace std;
int main() {
    String s1("abcdefg");

    char ch = s1[2];
    cout << ch << endl;  // 输出c

    //为什么[]的返回值是字符串的引用?因为一个函数,如果返回值是引用的话,就可以出现在表达式的左边,这样就能重新赋值。
    s1[2] = 'A';
    s1.Display();  // 输出abAdefg

    const String s2("xyzabc");
    //s2[2] = 'M';  // 这边会调用char& operator[](unsigned int index) const这个重载。因为是const对象,所以希望这个操作是不允许的;解决方案:前面加上const,变成const char& operator[](unsigned int index) const;这样的话,这句在编译的时候就会报错
    ch = s2[2];  // 希望这个操作是允许的
    s2.Display();  // 输出xyMabc

    String s3 = "xxx";
    String s4 = "yyy";

    String s5 = s3 + s4;
    s5.Display();

    s3 += s4;
    s3.Display();
    return 0;
}

10、<<和>>运算符重载

//String.h
#ifndef STRING_H
#define STRING_H

#include <iostream>
using namespace std;

class String {
public:
    String(const char* str = "");
    String(const String& other);  // 拷贝构造

    // 当你使用obj1 = obj2的时候,也是浅拷贝,即obj1.str_ = obj2.str_,所以要重载等号运算符,在里面进行深拷贝
    String& operator=(const String& other);
    String& operator=(const char* str);

    bool operator!() const;

    char& operator[](unsigned int index);
    const char& operator[](unsigned int index) const;

    //+运算符重载(最好用友元的方式来重载)
    friend String operator+(const String& s1, const String& s2);
    //+=运算符重载
    String& operator+=(const String& other);
    // << 运算符重载
    friend ostream& operator<<(ostream& os, const String& str);
    // >> 运算符重载
    friend istream& operator>>(istream& is, String& str);

    void Display() const;
    ~String(void);

private:
    static char* AllocAndCopy(const char* str);
    char* str_;
};

#endif //STRING_H
//String.cpp
include "String.h"
#include "String.h"
#include <string.h>
#include <iostream>
using namespace std;

String::String(const char* str)
{
    str_ = AllocAndCopy(str);
}

String::String(const String& other)
{
    str_ = AllocAndCopy(other.str_);
}

String& String::operator=(const String& other)
{
    if (this == &other)
        return *this;

    delete[] str_;
    str_ = AllocAndCopy(other.str_);
    return *this;
}

char* String::AllocAndCopy(const char* str)
{
    int len= strlen(str)+ 1;
    char* newStr= new char[len];
    memset(newStr, 0, len);
    strcpy(newStr, str);

    return newStr;
}
String& String::operator=(const char* str)
{
    delete[] str_;
    str_ = AllocAndCopy(str);
    return *this;
}

bool String::operator!() const
{
    return strlen(str_) != 0;
}

char& String::operator[](unsigned int index)
{
    return str_[index];
    // 因为这里面的代码和const的代码一样,所以最好合并成同一份代码
    // 做法是,non const 版本调用const版本
    return const_cast<char&>(static_cast<const String&>(*this)[index]);
}

const char& String::operator[](unsigned int index) const
{
    return str_[index];
}

void String::Display() const
{
    cout << str_ << endl;
}

String::~String()
{
    delete[] str_;
}

String operator+(const String& s1, const String& s2)
{
    int len = strlen(s1.str_) + strlen(s2.str_);
    char* newStr = new char[len];
    memset(newStr, 0, len);
    strcpy(newStr, s1.str_);
    strcat(newStr, s2.str_);

    String tmp(newStr);
    delete newStr;
    return tmp;
}

String& String::operator+=(const String& other)
{
    int len = strlen(str_) + strlen(other.str_);
    char* newStr = new char[len];
    memset(newStr, 0, len);
    strcpy(newStr, str_);
    strcat(newStr, other.str_);

    delete[] str_;
    str_ = newStr;
    return *this;
}

ostream& operator<<(ostream& os, const String& str)
{
    os << str.str_;
    return os;
}

istream& operator>>(istream& is, String& str)
{
    char tmp[1024];
    cin >> tmp;
    str = tmp;
    return is;
}
// main.cpp
#include <iostream>
#include "String.h"
using namespace std;
int main() {
    String s1("abcdefg");

    char ch = s1[2];
    cout << ch << endl;  // 输出c

    //为什么[]的返回值是字符串的引用?因为一个函数,如果返回值是引用的话,就可以出现在表达式的左边,这样就能重新赋值。
    s1[2] = 'A';
    s1.Display();  // 输出abAdefg

    const String s2("xyzabc");
    //s2[2] = 'M';  // 这边会调用char& operator[](unsigned int index) const这个重载。因为是const对象,所以希望这个操作是不允许的;解决方案:前面加上const,变成const char& operator[](unsigned int index) const;这样的话,这句在编译的时候就会报错
    ch = s2[2];  // 希望这个操作是允许的
    s2.Display();  // 输出xyMabc

    String s3 = "xxx";
    String s4 = "yyy";

    String s5 = s3 + s4;
    s5.Display();

    s3 += s4;
    s3.Display();

    cout << s3 << endl;

    String s7;
    cin >> s7;
    cout << s7 << endl;
    return 0;
}

11、类型转换运算符的重载

12、指针运算符->

#include <iostream>
using namespace std;
class DBHelper
{
public:
    DBHelper()
    {
        cout << "DB..." << endl;
    }
    ~DBHelper()
    {
        cout << "~DB..." << endl;
    }
    void Open()
    {
        cout << "Open..." << endl;
    }
    void Close()
    {
        cout << "Close..." << endl;
    }
    void Query()
    {
        cout << "Query..." << endl;
    }
};

class DB
{
public:
    DB()
    {
        db_ = new DBHelper();
    }
    ~DB()
    {
        delete db_;
    }

    DBHelper* operator->()
    {
        return db_;
    }

private:
    DBHelper* db_;
};
int main() {
    // ->指针运算符(一个指针A包装了另一个指针B,利用了A生命周期结束的时候的确定性析构,在析构中销毁B)
    // 相当于智能指针
    DB db;
    db->Open();
    db->Query();
    db->Close();

    return 0;
}

13、operator new、operator delete的重载

new有三种用法

new operator:不能被重载

operator new

placement new

#include <iostream>
using namespace std;

//类中operator new、operator delete的重载
class Test
{
public:
    Test(int n):n_(n)
    {
        cout << "Test(int n):n_(n)" << endl;
    }

    Test(const Test& other)
    {
        cout << "Test(const Test& other)" << endl;
    }

    ~Test()
    {
        cout << "~Test()" << endl;
    }

    // 重载operator new
    void* operator new(size_t size)
    {
        cout << "void* operator new(size_t size)" << endl;
        void* p = malloc(size);
        return p;
    }

    // 重载operator delete
    void operator delete (void* p)
    {
        cout << "void operator delete (void* p)" << endl;
        free(p);
    }
    // 这两个可以共存,看你是调用哪个
    void operator delete (void* p, size_t size)
    {
        cout << "void operator delete (void* p, size_t size)" << endl;
        free(p);
    }

    // 不同参数的new
    void* operator new(size_t size, const char* file, long line)
    {
        cout << "void* operator new(size_t size, const char* file, long line)" << endl;
        cout <<  file << ":" << line << endl;
        void* p = malloc(size);
        return p;
    }

    // 重载operator delete
    void operator delete (void* p, const char* file, long line)
    {
        cout << "void operator delete (void* p, const char* file, long line)" << endl;
        cout <<  file << ":" << line << endl;
        free(p);
    }

    // 重载placement new
    void* operator new(size_t size, void* p)
    {
        cout << "placement new" << endl;
        return p;
    }

    void operator delete(void*, void*)
    {
        cout << "placement delete" << endl;
    }

    int n_;
};

// 全局operator new、operator delete的重载
// 重载operator new
void* operator new(size_t size)
{
    cout << "global void* operator new(size_t size)" << endl;
    void* p = malloc(size);
    return p;
}

// 重载operator delete
void operator delete (void* p)
{
    cout << "global void operator delete (void* p)" << endl;
    free(p);
}

// 重载operator new
void* operator new[](size_t size)
{
    cout << "global void* operator new[](size_t size)" << endl;
    void* p = malloc(size);
    return p;
}

// 重载operator delete
void operator delete[](void* p)
{
    cout << "global void operator delete[] (void* p)" << endl;
    free(p);
}

int main() {
    Test* p1 = new Test(100);  // 这边是调用 new operator这个函数;这个函数相当于调用operator new 然后调用构造函数,两个函数的结合
    delete p1;

    char* str = new char;
    delete str;

    char* str2 = new char[100];
    delete []str2;

    char chunk[10];
    Test* p2 = new (chunk) Test(200);  // 调用placement new,不分配内存,是在chunk这段内存上构造对象的;然后调用operator new 然后调用构造函数
    cout << p2->n_ << endl;
    p2->~Test();    // 显示调用析构函数,这边不能用delete,因为是在chunk上面的内存

    //Test* p3 = (Test*)chunk;  // 强制转化
    Test* p3 = reinterpret_cast<Test*>(chunk);
    cout << p3->n_ << endl;

    Test* p4 = new(__FILE__, __LINE__) Test(300);
    delete p4;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux中常见的基本指令(上)

目录 一、ls指令 1. ls 2. ls -l 3. ls -a 4.ls -F 二、qwd指令 三、cd指令 1. cd .. 2. cd / / / 3. cd ../ / / 4. cd ~ 5. cd - 五、mkdir指令 六、rmdir指令和rm指令 一、ls指令 语法 &#xff1a; ls [ 选项 ][ 目录或文件 ] 。 功能 &#xff1a;对于目录…

手机号码携号转网查询保障用户权益、信息透明、优化用户体验

携号转网服务是指在同一本地网范围内&#xff0c;蜂窝移动通信用户&#xff08;不含物联网用户&#xff09;变更签约的基础电信业务经营者而用户号码保持不变的一项服务。近年来&#xff0c;随着通信行业的不断发展&#xff0c;携号转网服务已成为满足用户个性化需求、提升服务…

VBA让按钮消失

要求 用VBA搞小程序&#xff0c;有个录入数据的按钮&#xff0c;点击后进行录入数据的操作&#xff0c;操作完成后这个按钮就是灰的&#xff0c;点不动&#xff0c;这个怎么做&#xff1f; 实现过程 没找到让按钮变灰的方法&#xff0c;退而求其次&#xff0c;让按钮消失。 …

怎么更改图片格式?图片在线转格式的使用方法

现在很多的平台在上传图片的时候&#xff0c;都会有规定要求的大小、格式、尺寸&#xff0c;只有符合要求的图片才可以正常上传。在网上传图时想要快速的修改图片格式&#xff0c;比较简单的一个方法就是在使用在线图片格式转换的工具就能够快速处理&#xff0c;下面将图片转格…

发现没:随便搞个B端页面,就想在客户那里过关,难啦。

客户对B端界面要求越来越高的原因可以有以下几点&#xff1a; 用户体验要求提升&#xff1a;随着用户对移动应用和网页的使用经验增加&#xff0c;他们对于界面的交互、流畅性和易用性要求也越来越高。他们希望能够在使用B端应用时&#xff0c;能够快速、方便地完成任务&#…

Pooling Sequencing

1、混合(Pooling)样本测序研究 https://www.jianshu.com/p/19ce438ccccf 1.1 混合测序基础 测序成本虽然下降了,但对于植物育种应用研究来说还是很高,动不动就上百群体,小小植物个体价值又低,测完了很可能后面就用不到了。这时,混合样本测序是一种省钱的好办法。 混池…

Jetpack架构组件_4. 数据绑定库页面传递数据

本篇介绍数据源从activity_main&#xff08;1级页面&#xff09;传递给include布局&#xff08;2级页面&#xff09;。 1.实现步骤 step1.修改build.gradle文件 修改app模块下的build.gradle文件&#xff0c;增加如下内容&#xff1a; dataBinding {enabled true} step2.创建…

GPT-4o:引领人工智能新时代的强大引擎

前言 GPT-4o的推出&#xff0c;让我们再次感受到了人工智能技术的魅力。它不仅在技术上取得了显著突破&#xff0c;还为我们带来了广泛的应用前景。下面&#xff0c;我将从几个方面来谈谈GPT-4o的魅力。 一、技术突破&#xff0c;令人惊叹 1. 多模态处理能力的飞跃&#xff…

TC3xx分析--如何提高系统运行效率(1)

目录 1.Tricore寻址模式 2.lsl链接文件Section分析 3.小结 1.Tricore寻址模式 今天聊个好玩的事情。 之前ARM培训的时候&#xff0c;他们对于函数形参的先后顺序、数据类型、对齐方式等等做了介绍&#xff0c;详细分析了上述操作不同写法对于CPU的通用寄存器使用效率上的影…

【linux】运维-基础知识-认知hahoop周边

1. HDFS HDFS&#xff08;Hadoop Distributed File System&#xff09;–Hadoop分布式文件存储系统 源自于Google的GFS论文&#xff0c;HDFS是GFS的克隆版 HDFS是Hadoop中数据存储和管理的基础 他是一个高容错的系统&#xff0c;能够自动解决硬件故障&#xff0c;eg&#xff1a…

【旧文更新】基于OpenCV的Python人脸识别、检测、框选 (遍历目录下所有照片依次识别 视频随时标注)

【旧文更新】基于OpenCV的Python人脸识别、检测、框选 &#xff08;遍历目录下所有照片依次识别 视频随时标注&#xff09; 文章目录 关于旧文新发一、功能概览二、使用说明三、分部测试功能程序1.遍历目录功能2.界面获取目录功能3.人脸框选功能4.摄像头及框选功能5.延时功能 …

若依框架官网

RuoYi 若依官方网站 |后台管理系统|权限管理系统|快速开发框架|企业管理系统|开源框架|微服务框架|前后端分离框架|开源后台系统|RuoYi|RuoYi-Vue|RuoYi-Cloud|RuoYi框架|RuoYi开源|RuoYi视频|若依视频|RuoYi开发文档|若依开发文档|Java开源框架|Java|SpringBoot|SrpingBoot2.0…

Linux--进程间通信(2)(有名管道)

目录 1.原理 2.创建命名管道 3.使用命名通道实现简单的通信 4.使用创建的命名管道 1.原理 匿名管道没有名称&#xff0c;它们是通过句柄在父进程和子进程之间传递的。这意味着匿名管道只能用于具有父子关系的进程之间。 但如果程序之间没关系&#xff0c;那么这时候就要用…

香橙派AIpro初体验

1.开发板资料 开发板资源 产品介绍主页&#xff1a;http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-AIpro.html开发板案例源码&#xff1a;https://gitee.com/ascend/EdgeAndRobotics工具&原理图&案例源码&开发手册&#x…

Centos安装,window、ubuntus双系统基础上安装Centos安装

文章目录 前言一、准备工作二、开始安装1、2、首先选择DATE&TIME2、选择最小安装3、 选择安装位置 总结 前言 因工作需要&#xff0c;我需要在工控机上额外装Centos7系统&#xff0c;不过我是装在机械硬盘上了不知道对性能是否有影响&#xff0c;若有影响&#xff0c;后面…

整理了六个正规靠谱的兼职赚钱软件,适合普通人做的兼职副业~

​随着互联网时代的到来&#xff0c;越来越多的人选择通过互联网赚钱。在这篇文章中&#xff0c;我们将探讨一些可以在网上长期赚钱的方法。 在网络上面其实有很多的赚钱方法&#xff0c;尽管方法很多&#xff0c;但是对于一些网络新手&#xff0c;刚进入互联网圈子不久的伙伴…

gradio image 类型

3种类型&#xff0c;默认是 numpy.array numpy.array PIL.Image str file path. 互相转换 # 从路径到 numpy.ndarray import cv2 image_mask cv2.imread(imagePath) print(type(image_mask))# 从路径到 PIL.IMAGE from PIL import Image image_maskImage.open(imagePath) pri…

记录第一次使用U盘重装系统(win10专业版)的流程与总结

写在前面 刚进大学那会儿不懂电脑&#xff0c;什么东西都往 C 盘装&#xff0c;以至于很多环境、文件这些都很乱 尽管我已经把能移的都移动到 D盘了&#xff0c;能清理的东西也清理了&#xff0c;C 盘还是时不时会爆红 刚好最近 CTF 比赛打得差不多了&#xff0c;因此勇师傅决定…

2024 GIAC 全球互联网架构大会:拓数派向量数据库 PieCloudVector 架构设计与案例实践

5月24-25日&#xff0c;msup 和高可用架构联合举办了第11届 GIAC 全球互联网架构大会。会议聚焦“共话AI技术的最新进展、架构实践和未来趋势”主题&#xff0c;邀请了 100 余位行业内的领军人物和革新者&#xff0c;分享”Agent/RAG 技术、云原生、基座大模型“等多个热门技术…

以果决其行的古圣先贤

大家好&#xff0c;昨天给大家讲倪海夏老师以果决其行&#xff0c;这个思维逻辑,能解天下的万事万物&#xff0c;讲之前想的时候&#xff0c;想到了要讲历史上的人物&#xff0c;但是讲的当时忘了&#xff0c;今天补出来。 我们现在往前捋&#xff0c;在建国以后&#xff0c;我…