11C++常用函数

C++学习笔记

文章目录

  • C++学习笔记
    • 1.C++ 迭代器
      • 1.1emplace_back()
        • 1.1.1用法同push_back()
        • 1.1.2emplace_back()
    • 2.erase()
    • 3.to_string()
    • 4.vector容器的resize()和reserve()
    • 6.for(auto x : num) 语法
      • 6.1关于是否要加 `&`
    • 7.内联函数
      • 7.1为什么要用内联函数?
      • 7.2将内联函数放入头文件
      • 7.3 慎用内联
    • 8.c++中(:)和(::)的用法
        • 8.1(:)的用法
        • 8.2双冒号(::)用法
    • 9.运算符优先级和结合性一览表
        • 一些容易出错的优先级问题
    • 10.vector中二维数组的遍历
        • 10.1迭代器遍历
        • 10.2下标遍历
    • 11.NULL和nullptr类型区别

1.C++ 迭代器

  1. 背景: 指针可以用来遍历存储空间连续的数据结构,但是对于存储空间费连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历。
    定义:迭代器是一种检查容器内元素并遍历元素的数据类型。

    常用迭代器类型如下:
    这里写图片描述
    如上图所示,迭代器类型主要支持两类,随机访问和双向访问。其中vector和deque支持随机访问,list,set,map等支持双向访问。
    1)随机访问:提供了对数组元素进行快速随机访问以及在序列尾部进行快速插入和删除操作。
    2)双向访问:插入和删除所花费的时间是固定的,与位置无关。

1.1emplace_back()

1.1.1用法同push_back()

push_back 是 C++ STL(标准模板库)中 std::vector 容器的一个成员函数,用于在 vector 的末尾添加一个元素。这个函数会扩展 vector 的大小以容纳新的元素,并返回 void

当你调用 push_back 时,它会做以下几件事:

  1. 如果 vector 有足够的容量来容纳新元素,那么它将简单地在末尾添加该元素。
  2. 如果 vector 没有足够的容量,push_back 将会自动分配更多的内存,并可能将现有元素复制到新的内存位置,然后将新元素添加到末尾。

语法:

void push_back(const value_type& x);

push_back 是向 vector 添加元素的一种非常高效的方式,特别是当你不知道要添加多少元素时,因为它会自动处理内存分配。然而,如果你知道将要添加的元素数量,使用 reserve 函数预先分配足够的内存可以提高性能,因为这样可以减少多次内存分配和复制操作。

  • x 是要添加到 vector 末尾的元素。
1.1.2emplace_back()

emplace_back 是 C++ STL(标准模板库)中的一个成员函数,它属于 std::vectorstd::dequestd::list 等序列容器。emplace_back 用于在容器的末尾构造一个新元素,而不是先构造一个元素再将其插入到容器中,这样可以提高效率。

使用 emplace_back 时,你可以直接在容器中构造元素,而不需要使用临时对象。这减少了复制或移动操作,从而提高了性能。emplace_back 接受构造新元素所需的参数,并使用这些参数在容器的末尾就地构造元素。

以下是 emplace_back 的一个使用示例:

#include <vector>

int main() {
    std::vector<int> vec;
    vec.emplace_back(10);  // 在末尾添加一个值为10的整数
    vec.emplace_back();    // 添加一个默认构造的整数,其值为0

    return 0;
}

2.erase()

有三种用法:

(1)erase(pos, n); 删除从pos开始的n个字符,例如erase( 0, 1),删除0位置的一个字符,即删除第一个字符。

(2)erase(position); 删除position处的一个字符(position是个string类型的迭代器)。

(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器)。


#include <iostream>
#include <string>
using namespace std;
 
int main ()
{
  string str ("This is an example phrase.");
  string::iterator it;
 
  // 第(1)种用法
  str.erase (10,8);
  cout << str << endl;        // "This is an phrase."
 
  // 第(2)种用法
  it=str.begin()+9;
  str.erase (it);
  cout << str << endl;        // "This is a phrase."
 
  // 第(3)种用法
  str.erase (str.begin()+5, str.end()-7);
  cout << str << endl;        // "This phrase."
  return 0;
}

3.to_string()

在C++中,to_string 是一个函数模板,它提供了一种将数值类型转换为字符串的方法。to_string 函数属于 <sstream><iomanip> 头文件中的 <<string>> 命名空间,因此在使用之前需要包含这些头文件。

to_string 函数可以处理多种数值类型,包括整数类型(如 intlonglong long 等)和浮点数类型(如 floatdouble 等)。它将数值转换为一个 std::string 类型的对象。

以下是 to_string 函数的一些使用示例:

#include <iostream>
#include <string> // for std::string and std::to_string

int main() {
    int i = 123;
    double d = 456.789;
    char c = 'a';

    // 转换整数为字符串
    std::string str1 = std::to_string(i);
    std::cout << "Integer as string: " << str1 << std::endl;

    // 转换浮点数为字符串
    std::string str2 = std::to_string(d);
    std::cout << "Double as string: " << str2 << std::endl;

    // 转换字符为字符串
    std::string str3 = std::to_string(c);
    std::cout << "Character as string: " << str3 << std::endl;

    return 0;
}

输出将会是:

Integer as string: 123
Double as string: 456.789
Character as string: a

4.vector容器的resize()和reserve()

vector 的 reserve 增加了 vector 的 capacity ,但是它的 size 没有改变!而 resize 改变了 vector 的 capacity 同时也增加了它的 size !

原因如下:
reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。 加入新的元素时,要调用push_back() / insert()函数。

resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了, 因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的。

下面是这两个函数使用例子:

不管是调用resize还是reserve,二者对容器原有的元素都没有影响。

vector<int> myVec;
myVec.reserve(100);     // 新元素还没有构造, 
                                       // 此时不能用[]访问元素
for (int i = 0; i < 100; i++)
{ 
     myVec.push_back(i); //新元素这时才构造
}
myVec.resize(102);      // 用元素的默认构造函数构造了两个新的元素
myVec[100] = 1;           //直接操作新元素
myVec[101] = 2;  
例子2#include <vector>
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    vector<int> vect;
    
    vect.push_back(1);
    vect.push_back(2);
    vect.push_back(3);
    vect.push_back(4);
    vect.reserve(100);
    cout << vect.size() << endl;  //size为4,但是capacity为100
    int i = 0;
    for (i = 0; i < 104; i++)
    {
        cout<<vect[i]<<endl;
    }
    return 0;
}
例子3#include <vector>
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    vector<int> vect;    
    vect.push_back(1);
    vect.push_back(2);
    vect.push_back(3);
    vect.push_back(4);
    vect.resize(100);    //新的空间不覆盖原有四个元素占有的空间,现在size和capacity都是100
    cout<<vect.size()<<endl;
    int i = 0;
    for (i = 0; i < 104; i++)
    {
        cout<<vect[i]<<endl;  
    }
    return 0;
}
例子4#include <vector>
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    vector<int> vect;        
    vect.resize(100);    //分配100个空间
    vect.push_back(1);
    vect.push_back(2);
    vect.push_back(3);
    vect.push_back(4);
    cout << vect.size() <<endl; //现在size和capacity都是104
    int i = 0;
    for (i = 0; i < 104; i++)
    {
        cout<<vect[i]<<endl;  
    }
    return 0;
}

6.for(auto x : num) 语法

C++11新增了一种循环:基于范围的for循环,这简化了一种常见的循环任务:对数组和容器类的每个元素都执行相同的操作

for (auto x : nums)

作用就是迭代容器中所有的元素,每一个元素的临时名字就是x,等同于下边代码

for (vector<int>::iterator iter = nums.begin(); iter != nums.end(); iter++)

语法形式

for(数据类型 变量 : 序列)
	循环语句
  • 序列

  • 可以是花括号括起来的初始值列表、数组、vectorstring,这些类型的特点是拥有能返回迭代器的 beginend成员

  • 数据类型:变量

  • 序列中的每个元素都能转换成该变量的类型,最简单的方法是使用auto类型说明符。

  • 若需要对序列中的元素进行写操作,则需要声明成引用类型&

【示例1】

#include <iostream>
using namespace std;
int main(){    
    int num[5]={1,2,3,4,5};    
    for(auto x:num)        
       cout<<x<<endl;    
    return 0;
}

【示例2】

#include <iostream>
using namespace std;
int main(){    
string s;    
cin>>s;    
cout<<s<<endl;    
for (auto &c : s)        
    c=toupper(c);    
cout<<s<<endl;
}

toupper 函数用于将小写字母转换为大写字母。它是 <cctype> 头文件中定义的一个标准库函数。toupper 函数接受一个 char 类型的参数,并返回转换后的字符。如果输入的字符不是小写字母,它将原样返回该字符。

【示例3】

#include <iostream>
using namespace std;
int main(){    
    for(auto x:{1,2,3,4,5})      
    cout<<x<<endl;
}

【示例4】下面的例子将vector对象中的每个元素都翻倍

vector<int>v={0,1,2,3,4};
//因为要对v中的元素进行写操作,所以是引用类型
for(auto &r : v)
	r*= 2;

6.1关于是否要加 &

  • 不加引用是取值,加引用是取引用(相当于指针)。
  • 如果数组中的对象不大(比如 int,char 等),以及明确要求不修改数组本身,则可以不加引用,每次取值拷贝。
  • 如果数组中的对象很大,或者想要修改,则需要取引用。

7.内联函数

7.1为什么要用内联函数?

在C++中我们通常定义以下函数来求两个整数的最大值:

int max(int a, int b)
{
    return a > b ? a : b;
}

为这么一个小的操作定义一个函数的好处有:

① 阅读和理解函数 max 的调用,要比读一条等价的条件表达式并解释它的含义要容易得多

② 如果需要做任何修改,修改函数要比找出并修改每一处等价表达式容易得多

③ 使用函数可以确保统一的行为,每个测试都保证以相同的方式实现

④函数可以重用,不必为其他应用程序重写代码

虽然有这么多好处,但是写成函数有一个潜在的缺点:调用函数比求解等价表达式要慢得多。在大多数的机器上,调用函数都要做很多工作:调用前要先保存寄存器,并在返回时恢复,复制实参,程序还必须转向一个新位置执行

C++中支持内联函数,其目的是为了提高函数的执行效率,用关键字 inline 放在函数定义(注意是定义而非声明,下文继续讲到)的前面即可将函数指定为内联函数,内联函数通常就是将它在程序中的每个调用点上“内联地”展开,假设我们将 max 定义为内联函数:

inline int max(int a, int b)
{
    return a > b ? a : b;
}

则调用: cout << max(a, b) << endl;

在编译时展开为: cout << (a > b ? a : b) << endl; 从而消除了把 max写成函数的额外执行开销。

7.2将内联函数放入头文件

关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用。

如下风格的函数 Foo 不能成为内联函数:

inline void Foo(int x, int y);   // inline 仅与函数声明放在一起   
void Foo(int x, int y)
{
    //...
} 

而如下风格的函数 Foo 则成为内联函数:

void Foo(int x, int y);   
inline void Foo(int x, int y)   // inline 与函数定义体放在一起

定义在类声明之中的成员函数将自动地成为内联函数,例如:

    class A
    {  
    public:
        void Foo(int x, int y) { ... }   // 自动地成为内联函数  
    } 

但是编译器是否将它真正内联则要看 Foo函数如何定义

内联函数应该在头文件中定义,这一点不同于其他函数。编译器在调用点内联展开函数的代码时,必须能够找到 inline 函数的定义才能将调用函数替换为函数代码,而对于在头文件中仅有函数声明是不够的。

当然内联函数定义也可以放在源文件中,但此时只有定义的那个源文件可以用它,而且必须为每个源文件拷贝一份定义(即每个源文件里的定义必须是完全相同的),当然即使是放在头文件中,也是对每个定义做一份拷贝,只不过是编译器替你完成这种拷贝罢了。但相比于放在源文件中,放在头文件中既能够确保调用函数是定义是相同的,又能够保证在调用点能够找到函数定义从而完成内联(替换)。

但是你会很奇怪,重复定义那么多次,不会产生链接错误?

我们来看一个例子:

// 文件A.h 代码如下:
class A
{
public:
    A(int a, int b) : a(a),b(b){}
    int max();
private:
    int a;
    int b;
};
// 文件A.cpp 代码如下:
#include "A.h"
inline int A::max()
{
    return a > b ? a : b;
}
// 文件Main.cpp 代码如下:

    #include <iostream>
    #include "A.h"
    using namespace std;
    inline int A::max()
    {
        return a > b ? a : b;
    }

    int main()
    {
        A a(3, 5);
        cout << a.max() << endl;
        return 0;
    }

一切正常编译,输出结果:5

倘若你在Main.cpp中没有定义max内联函数,那么会出现链接错误:
error LNK2001: unresolved external symbol "public: int __thiscall A::max(void)" (?max@A@@QAEHXZ)main.obj
找不到函数的定义,所以内联函数可以在程序中定义不止一次,只要 inline 函数的定义在某个源文件中只出现一次,而且在所有源文件中,其定义必须是完全相同的就可以。

在头文件中加入或修改 inline 函数时,使用了该头文件的所有源文件都必须重新编译。

7.3 慎用内联

“如果所有的函数都是内联函数,还用得着“内联”这个关键字吗?

内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。以下情况不宜使用内联:

(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。

(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。

8.c++中(:)和(::)的用法

8.1(:)的用法

(1)表示机构内位域的定义(即该变量占几个bit空间)。

typedef struct _XXX{
unsigned char a:4;
unsigned char c;
}; XXX

(2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型。

struct _XXX{
_XXX() : y(0xc0) {}
};

(3)public:private:后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"public:”"private:”出现为止。"private:"为默认处理。

(4)类名冒号后面的是用来定义类的继承。

class 派生类名 : 继承方式 基类名
{
派生类的成员
};

继承方式:public、private和protected,默认处理是public。

8.2双冒号(::)用法

(1)表示“域操作符”

  • 例:声明了一个类A,类A里声明了一个成员函数void f(),但没有在类的声明里给出f的定义,那么在类外定义f时, 就要写成void A::f(),表示这个f()函数是类A的成员函数。

(2)直接用在全局函数前,表示是全局函数

  • 例:在VC里,你可以在调用API 函数里,在API函数名前加::

(3)表示引用成员函数及变量,作用域成员运算符

  • 例:System::Math::Sqrt() 相当于System.Math.Sqrt()

9.运算符优先级和结合性一览表

优先级运算符名称或含义使用形式结合方向说明
1[]数组下标数组名[常量表达式]左到右
()圆括号(表达式) 函数名(形参表)
.成员选择(对象)对象.成员名
->成员选择(指针)对象指针->成员名
2-负号运算符-表达式右到左单目运算符
(类型)强制类型转换(数据类型)表达式
++自增运算符++变量名 变量名++单目运算符
自减运算符–变量名 变量名–单目运算符
*取值运算符*指针变量单目运算符
&取地址运算符&变量名单目运算符
!逻辑非运算符!表达式单目运算符
~按位取反运算符~表达式单目运算符
sizeof长度运算符sizeof(表达式)
3/表达式 / 表达式左到右双目运算符
*表达式*表达式双目运算符
%余数(取模)整型表达式%整型表达式双目运算符
4+表达式+表达式左到右双目运算符
-表达式-表达式双目运算符
5<<左移变量<<表达式左到右双目运算符
>>右移变量>>表达式双目运算符
6>大于表达式>表达式左到右双目运算符
>=大于等于表达式>=表达式双目运算符
<小于表达式<表达式双目运算符
<=小于等于表达式<=表达式双目运算符
7==等于表达式==表达式左到右双目运算符
!=不等于表达式!= 表达式双目运算符
8&按位与表达式&表达式左到右双目运算符
9^按位异或表达式^表达式左到右双目运算符
10|按位或表达式|表达式左到右双目运算符
11&&逻辑与表达式&&表达式左到右双目运算符
12||逻辑或表达式||表达式左到右双目运算符
13?:条件运算符表达式1? 表达式2: 表达式3右到左三目运算符
14=赋值运算符变量=表达式右到左
/=除后赋值变量/=表达式
*=乘后赋值变量*=表达式
%=取模后赋值变量%=表达式
+=加后赋值变量+=表达式
-=减后赋值变量-=表达式
<<=左移后赋值变量<<=表达式
>>=右移后赋值变量>>=表达式
&=按位与后赋值变量&=表达式
^=按位异或后赋值变量^=表达式
|=按位或后赋值变量|=表达式
15,逗号运算符表达式,表达式,…左到右

上表中可以总结出如下规律:

  1. 结合方向只有三个是从右往左,其余都是从左往右。
  2. 所有双目运算符中只有赋值运算符的结合方向是从右往左。
  3. 另外两个从右往左结合的运算符也很好记,因为它们很特殊:一个是单目运算符,一个是三目运算符。
  4. C语言中有且只有一个三目运算符。
  5. 逗号运算符的优先级最低,要记住。
  6. 此外要记住,对于优先级:算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符。逻辑运算符中“逻辑非 !”除外。
一些容易出错的优先级问题

上表中,优先级同为1 的几种运算符如果同时出现,那怎么确定表达式的优先级呢?这是很多初学者迷糊的地方。下表就整理了这些容易出错的情况:

优先级问题表达式经常误认为的结果实际结果
. 的优先级高于 *(-> 操作符用于消除这个问题)*p.fp 所指对象的字段 f,等价于: (*p).f对 p 取 f 偏移,作为指针,然后进行解除引用操作,等价于: *(p.f)
[] 高于 *int *ap[]ap 是个指向 int 数组的指针,等价于: int (*ap)[]ap 是个元素为 int 指针的数组,等价于: int *(ap [])
函数 () 高于 *int *fp()fp 是个函数指针,所指函数返回 int,等价于: int (*fp)()fp 是个函数,返回 int*,等价于: int* ( fp() )
== 和 != 高于位操作(val & mask != 0)(val &mask) != 0val & (mask != 0)
== 和 != 高于赋值符c = getchar() != EOF(c = getchar()) != EOFc = (getchar() != EOF)
算术运算符高于位移 运算符msb << 4 + lsb(msb << 4) + lsbmsb << (4 + lsb)
逗号运算符在所有运 算符中优先级最低i = 1, 2i = (1,2)(i = 1), 2 逗号表达式的值为2

10.vector中二维数组的遍历

10.1迭代器遍历
void reverse_iterator(vector<vector<int>> vec)
{
    vecotr<int>::iterator it;
    vector<vector<int>>::iterator iter;
    vector<int> vec_tmp;
    
    for (iter = vec.begin(); iter != vec.end(); iter++)
    {
        vec_tmp = *iter;
        for (it = vec_tmp.begin(); it != vec_tmp.end(); it++)
            cout << *it << " ";
        cout << endl;
    }
}
void reverse_iterator(vector<vector<int>> vec)
{
    for (vector<vector<int>>::iterator it = vec.begin(); it != vec.end(); it++)
        for (vector<int>:: iterator iter = (*it).begin(); iter != (*it).end(); iter++)
        {
            cout << *iter << " ";
        }
}
10.2下标遍历
void reverse_index(vector<vector<int>> vec)
{
    for (int i = 0; i < vec.size(); i++)
    {
        for (int j = 0; j < vec[i].size(); j++)
            cout << vec[i][j] << " ";
        cout << endl;
    }
}

11.NULL和nullptr类型区别

  1. nullptr和NULL类型区别
  • NULL是一个无类型的东西,而且是一个宏。

    • 在C中,习惯将NULL定义为void*指针值0,但同时,也允许将NULL定义为整常数0
    • 在C++中,NULL却被明确定义为整常数0
  • nullptr是有类型的(放了在stddef头文件中),类型是 typdef decltype(nullptr) nullptr_t;

  1. C++中NULL使用存在的问题
  • 在c语言环境下,由于不存在函数重载等问题,直接将NULL定义为一个void*的指针就可以完美的解决一切问题。
  • 在c++环境下情况就复杂起来, 首先我们将void*直接赋值给一个指针是不合法的,编译器会报错。有重载或者模板推导的时候,编译器就无法给出正确结果。
    • 根本原因和C++的重载函数有关。C++通过搜索匹配参数的机制,试图找到最佳匹配(best-match)的函数,而如果继续支持void*的隐式类型转换,则会带来语义二义性(syntax ambiguous)的问题。
  1. nullptr的应用:
  • 如果我们的编译器是支持nullptr的话,那么我们应该直接使用nullptr来替代NULL的宏定义。正常使用过程中他们是完全等价的。
  • 0(NULL)和nullptr可以交换使用
  • 不能将nullptr赋值给整形

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

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

相关文章

袋鼠云产品功能更新报告10期|智能进化,近百项功能升级加速数智化转型

欢迎查阅袋鼠云第10期产品功能更新报告。本期&#xff0c;我们精心推出了72项新增和优化功能&#xff0c;致力于在数字化浪潮中为您提供更高效、更智能的服务。我们相信&#xff0c;这些新特性将为您的业务注入新活力&#xff0c;确保您在数字化转型的每一步都坚实而有力。 以…

大模型学习之菜鸟的进阶道路---工程迭代

我们的大模型学习开始了新篇章&#xff0c;这一章还是比较基础的调用api&#xff0c;有些朋友建议直接搞构造大模型&#xff0c;很显然这是很不科学的&#xff0c;我们先从基础学习&#xff0c;大模型本来就是很晦涩难懂的东西&#xff0c;并且知识体系十分庞大&#xff0c;所以…

618数码产品有什么推荐?四大2024“宝藏”数码产品推荐!

随着618购物节的热情逐渐升温&#xff0c;你是否在繁多且诱人的商品海洋中迷失方向&#xff0c;难以找到那最心仪的宝贝&#xff1f;团团在此特别为你精心挑选了一系列经过亲身体验的优质好物。这些推荐不仅时尚前沿&#xff0c;更贴合你的日常生活需求&#xff0c;确保实用与品…

电脑ip地址查询:快速定位你的网络位置(4种方法)

在互联网的浩瀚海洋中&#xff0c;每台联网的电脑都有一个独特的身份标识&#xff0c;那就是IP地址。无论是进行网络通信、定位问题还是安全防护&#xff0c;了解自己或他人的电脑IP地址都是非常关键的。那么&#xff0c;电脑ip地址查询怎么操作呢&#xff1f;本文将为你提供一…

RabbitMQ消息的发布确认机制详解

RabbitMQ发布确认机制确保消息从生产者成功传输到交换机和队列&#xff0c;提高系统可靠性。在Spring Boot项目中&#xff0c;通过配置publisher-confirm-type和publisher-returns&#xff0c;启用发布确认和消息返回机制。配置RabbitTemplate的确认回调和返回回调&#xff0c;…

黑龙江等保测评流程

黑龙江的等保测评过程是一个系统严谨的过程&#xff0c;目的在于保证信息系统的安全与机密性符合国家规定的要求。下面将详细介绍黑龙江等保测评的流程&#xff1a; 一、定级与备案 首先&#xff0c;企业要依据自身的业务特点、信息系统的重要性和所承载的信息的敏感程度&…

MyEclipse新手使用介绍

目录 1.MyEclipse诞生背景 2.作用 3.版本历史 4.优缺点 5.应用场景 6.如何使用 6.1.下载与安装 6.2.MyEclipse 菜单及其菜单项 7.创建和发布一个 Java 程序 7.1.创建 Java 程序 7.2.发布 Java 程序 8.示例 8.1. Hello World 示例 8.2. 简单Spring Boot 应用 8.3…

手动安装Nvidia驱动和CUDA Toolkit

1、打开cuda-toolkit 网站 CUDA Toolkit Archive | NVIDIA Developer 根据自己需要选择CUDA Toolkit版本&#xff0c;这里选择12.0.0 2、点击链接跳转到下载页面&#xff0c;选择操作系统类型和安装包类型 3、下载CUDA Toolkit 安装包 4、执行下载命令 wget https://develo…

Sora简介与其对新媒体短视频行业的影响

Sora简介 官网&#xff1a;https://openai.com/sora 当大家还在沉浸在GPT各种大语言模型的时候&#xff0c;OpenAI 悄无声息地发布了文生视频&#xff08;text-to-video&#xff0c;简称 t2v&#xff09;模型 Sora&#xff0c;这又是一个对AI冲击很大的突破了。Sora可以根据文…

什么是广告联盟变现

广告联盟变现&#xff0c;作为一种连接广告主与各类媒体平台的机制&#xff0c;正展现出强大的生命力和影响力。它为拥有流量资源的一方提供了将其转化为实际经济收益的有效途径。通过广告联盟&#xff0c;媒体平台可以与众多广告主建立合作关系&#xff0c;获取多样化的广告内…

Ubuntu系统安装docker以及安装yg系统所能使用到的插件

Ubuntu系统安装docker以及安装yg系统所能使用到的插件 前言&#xff1a;建议大家使用ubuntu系统的时候&#xff0c;直接永久关闭防火墙目前我们处于学习状态&#xff0c;这样有利于提高开发效率。 文章目录 Ubuntu系统安装docker以及安装yg系统所能使用到的插件一、安装docker二…

docker 拉取不到镜像的问题:拉取超时

error pulling image configuration: download failed after attempts6: dial tcp 31.13.94.10:443: i/o timeout 首先设置国内的镜像源&#xff1a;复制下面直接执行 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF{"registry-mirrors"…

通过在idea上搭建虚拟hadoop环境使用MapReduce做词频去重

idea上的MapReduce ​ 一般在开发中&#xff0c;若是等到环境搭配好了再进行测试或者统计数据&#xff0c;数据处理等操作&#xff0c;那会很耽误时间&#xff0c;所以一般都是2头跑&#xff0c;1波人去在客户机上搭建环境&#xff0c;1波人通过在idea上搭建虚拟hadoop环境&am…

uni-app uni-swipe-action 滑动操作状态恢复

按照uni-app官方文档的写法 当前同一条滑动确认之后 页面列表刷新 但是滑动的状态还在 入下图所示&#xff1a; 我们需要在滑动确认之后 页面刷新 滑动状态恢复 那么我们就来写一下这部分的逻辑&#xff1a; 首先&#xff0c;配置一下:show"isOpened[item.id]" chan…

学习笔记——网络参考模型——TCP/IP模型(网络层)

三、TCP/IP模型-网络层 1、IPV4报头 (1)IPV4报文格式 IP Packet(IP数据包)&#xff0c;其包头主要内容如下∶ Version版本∶4 bit&#xff0c;4∶表示为IPv4; 6∶表示为IPv6。 Header Length首部长度∶4 bit&#xff0c;代表IP报头的长度(首部长度)&#xff0c;如果不带Opt…

传输协议TCP-原理部分

传输控制协议TCP&#xff08;Transmission Control Protocol&#xff09;一种基于连接的可靠的稳定的无重复的传输协议。 1、TCP头部信息 TCP协议头部信息如下&#xff1a; 一共占用20个字节 16位源端口号&#xff1a;发送进程的主机端口16位目的端口号&#xff1a;接收主机…

工作备忘录软件有哪些 记事备忘提醒三合一的备忘录

在工作中&#xff0c;我总是觉得自己脑子好像不够用&#xff0c;一会儿是这个项目的进度要跟踪&#xff0c;一会儿是那个会议的要点要记录。每天都在忙碌与混乱中度过&#xff0c;我甚至开始怀疑自己是否适合这份工作。 备忘录不仅是一个简单的记事工具&#xff0c;像敬业签这…

MyBatis总结(2)- MyBatis实现原理(一)

Mybatis实现原理&#xff1a; 概括一句话&#xff1a;约定配置参数mybatis-config.xml&#xff0c;映射关系JavaBean-mapper.xml&#xff0c;用SqlSessionFactoryBuilder构建应用程序运行期间需要的SqlSessionFactory实例对象&#xff0c;当请求或方法需要执行CURD操作时&…

matlab使用教程(92)—流线图、流带图和流管图

1.使用向量数据显示流线图 MATLAB 向量数据集 wind 代表北美地区的气流。本示例结合使用了几种方法&#xff1a; 利用流线跟踪风速 利用切片平面显示数据的横截面视图 利用切片平面上的等高线提高切片平面着色的可见性 1.1确定坐标的范围 加载数据并确定用来定位切片平面…

TypeScript系列之-- 带你深层次理解对象类型回归本质探究原理

描述对象的数据类型&#xff1a; 使用class/constructor描述用type或interface描述 使用class/constructor描述 const a: Date ()> console.log(1) // Error 会报错缺少日期的一些属性 const a: Function ()> console.log(1) // Ok class Person { name: string …