C++初阶---C++入门(下)

news2024/11/20 2:41:05

目录

一、内联函数

1.内联函数的定义与底层机制

0x01.内联函数的定义

 0x02.内联函数的底层机制

2.内联函数的优缺点

优点:

缺点:

3.内联函数的使用建议

4.内联函数的注意事项

二、auto关键字(C++11)

1.代码示例

2.auto使用场景

0x01.迭代器遍历

0x02. Lambda表达式

0x03.范围for循环

0x04.复杂的类型推导

0x05.与decltype结合使用

 3.使用auto关键字注意事项

 0x01. 初始化是必需的

 0x02.auto 不能作为函数的参数 

 0x03.auto 不能直接用来声明数组 

 0x04.避免过度使用

 0x05.注意const和volatile的保留

 0x06.小心引用和指针的推导

 0x07.初始化表达式中的类型转换

 0x08.与模板结合使用时的小心

 4.auto关键字总结

三、基于范围的for循环(C++11)

1.范围for的语法

 2. 范围for的使用条件

 3.底层实现原理

 4.细节和注意事项

 5.范围for总结

 四、指针空值 nullptr(C++11)

1.nullptr的引入背景

2.nullptr与NULL的区别

3.nullptr的使用场景

0x01.初始化指针

0x02.比较指针

0x03.函数参数和返回值

0x05.避免类型混淆

 4.注意事项

 5.总结


一、内联函数

在C++编程中,内联函数(Inline Function)是一种强大的优化手段,它通过减少函数调用的开销来提高程序的执行效率。这里将深入探讨C++内联函数的底层机制、优缺点以及最佳实践,并插入一些示例代码以帮助你更好地理解。

1.内联函数的定义与底层机制

内联函数是C++语言中的一种特性,它允许程序员请求编译器将函数的定义(实现)直接插入到所有调用该函数的地方,而不是创建一个新的函数调用栈帧。这意味着当函数被调用时,它的代码会直接嵌入到调用处,而不是跳转到函数定义处执行。

0x01.内联函数的定义

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调 用建立栈帧的开销,内联函数提升程序运行的效率。

正常函数调用

内联函数调用

 从这里可以看到内联函数并没有建立栈帧,减少建立栈帧的开销从而提高程序的效率。

 0x02.内联函数的底层机制

  1. 内联请求与编译器决策

    • 当程序员使用inline关键字声明一个函数时,他们实际上是在向编译器提出一个内联请求
    • 编译器会根据函数的复杂性、大小、调用频率以及编译器的优化策略来决定是否接受这个请求。
    • 如果编译器决定不接受内联请求,该函数将被视为普通函数进行处理。
  2. 内联函数的展开

    • 当编译器接受内联请求时,它会在每个调用该函数的地方插入该函数的代码。
    • 这意味着每次函数调用都会被替换为函数体的实际代码。
    • 内联函数的展开是在编译时进行的,而不是在运行时
  3. 内联函数的局限性

    • 内联函数不能包含复杂的控制结构(如循环和递归),否则编译器可能会拒绝内联请求。
    • 内联函数通常用于小型、频繁调用的函数,以避免代码膨胀和编译时间增加。

2.内联函数的优缺点

优点

  1. 提高执行效率:内联函数避免了函数调用的开销,包括堆栈帧分配、参数传递和返回操作。
  2. 改善代码可读性:对于小型、简单的函数,内联函数可以使代码更易于阅读和理解。

缺点

  1. 代码膨胀:内联函数会导致调用处的代码膨胀,因为每次调用都会插入函数体的代码。
  2. 编译时间增加:编译器需要处理更多的代码,这可能会增加编译时间。
  3. 调试困难:由于代码被展开到调用点,调试时可能难以跟踪到原始的函数定义。

3.内联函数的使用建议

  1. 选择小型函数:仅内联小型函数,因为大型函数会产生代码膨胀,影响程序的执行效率。
  2. 避免递归函数:内联递归函数会导致堆栈溢出或编译器拒绝内联。
  3. 使用inline关键字:虽然inline只是一个建议,但使用它可以增加编译器内联函数的可能性。
  4. 剖析代码:使用剖析工具来识别哪些函数受益于内联。
  5. 函数定义放在头文件中:为了确保编译器在编译每个调用该函数的源文件时都能看到函数定义,通常将内联函数的定义放在头文件中。否则内联函数会认为在调用的地方展开,导致不生成地址。

4.内联函数的注意事项

  1. inline关键字只是建议inline关键字只是向编译器提出内联请求的建议,编译器可以选择是否接受这个请求。
  2. 避免过度使用:过度使用内联函数可能会导致代码膨胀和编译时间增加,从而降低程序的性能。
  3. 考虑代码的可移植性:在某些情况下,内联函数可能会导致代码在不同编译器或平台上的行为不一致。因此,在编写跨平台代码时,应谨慎使用内联函数。

二、auto关键字(C++11)

在C++11标准中,auto关键字被赋予了新的使命——类型推导。在此之前,C++中的auto主要用于声明变量的存储期为自动,即局部变量。然而,从C++11开始,auto关键字主要用于根据变量的初始化表达式自动推导其类型。

1.代码示例

int main()
{
	auto i = 42; // i的类型将被推断为int  
    auto ch = 'a';// ch的类型将被推断为char
	auto d = 3.14; // y的类型将被推断为double  
	auto z = "hello"; // z的类型将被推断为const char*


    cout << typeid(i).name() << endl;   // i
    cout << typeid(ch).name() << endl;  // c
    cout << typeid(d).name() << endl;   // d
    cout << typeid(z).name() << endl;  // P

    return 0;
}

运行结果如下 :

 

2.auto使用场景

 0x01.迭代器遍历

在使用STL容器(如std::vectorstd::list等)时,auto可以自动推导迭代器的类型,避免显式指定迭代器类型的繁琐。

#include <iostream>  
#include <vector>  
  
int main() 
{  
    std::vector<int> vec = {1, 2, 3, 4, 5};  
    for (auto it = vec.begin(); it != vec.end(); ++it) {  
        std::cout << *it << " ";  
    }  
    std::cout << std::endl;  
    return 0;  
}

0x02. Lambda表达式

#include <iostream>  
#include <algorithm>  
#include <vector>  
  
int main() 
{  
    std::vector<int> vec = {1, 2, 3, 4, 5};  
    auto print = [](int x) { std::cout << x << " "; };  
    std::for_each(vec.begin(), vec.end(), print);  
    std::cout << std::endl;  
    return 0;  
}

0x03.范围for循环

范围for循环是C++11引入的一种简化数组或容器遍历的语法,auto可以自动推导集合元素的类型。

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

0x04.复杂的类型推导

在处理复杂类型(如模板实例化后的类型、类型别名等)时,auto可以简化类型声明。

#include <iostream>  
#include <map>  
#include <string>  
  
int main() 
{  
    std::map<std::string, int> myMap = {{"apple", 1}, {"banana", 2}};  
    for (const auto& pair : myMap) {  
        std::cout << pair.first << ": " << pair.second << std::endl;  
    }  
    // 使用auto简化类型推导,避免显式指定std::pair<const std::string, int>  
    auto it = myMap.find("apple");  
    if (it != myMap.end()) {  
        std::cout << "Found apple with value: " << it->second << std::endl;  
    }  
    return 0;  
}

 0x05.与decltype结合使用

在某些情况下,你可能需要保留变量的constvolatile属性,或者需要推导出一个与现有变量相同类型的新变量。这时可以使用decltypeauto结合。

#include <iostream>  
  
int main() 
{  
    int x = 10;  
    decltype(auto) y = x; // y的类型是int,与x相同  
    const int z = 20;  
    decltype(auto) w = z; // w的类型是const int,保留了z的const属性  
    std::cout << "y: " << y << ", w: " << w << std::endl;  
    // 注意:不能修改w的值,因为它是const int类型  
    // w = 30; // 错误:不能给常量赋值  
    return 0;  
}

 3.使用auto关键字注意事项

 0x01. 初始化是必需的

auto变量必须在使用前进行初始化,因为auto是通过初始化表达式来推导类型的。未初始化的auto变量将导致编译错误。

auto x; // 错误:auto变量必须初始化  
auto y = 10; // 正确:y的类型被推导为int

0x02.auto 不能作为函数的参数 

#include<iostream>
using namespace std;
// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{
    
}

0x03.auto 不能直接用来声明数组 

#include<iostream>
using namespace std;
int main()
{
	int a[] = { 1,2,3 };
	auto b[] = { 4,5,6 };
	return 0;
}

0x04.避免过度使用

虽然auto可以简化代码,但过度使用可能会降低代码的可读性。特别是在类型信息对于理解代码逻辑很重要时,显式指定类型可能更清晰。

// 不推荐:过度使用auto可能导致代码难以阅读  
auto a = 5;  
auto b = "Hello";  
auto c = std::make_pair(a, b);  
  
// 推荐:在类型明确且重要时,显式指定类型  
int a = 5;  
std::string b = "Hello";  
std::pair<int, std::string> c = std::make_pair(a, b);

 0x05.注意constvolatile的保留

auto在推导类型时不会保留顶层constvolatile限定符。如果你需要保留这些限定符,可以使用decltype(auto)

const int x = 10;  
auto y = x; // y的类型是int,丢失了const限定符  
decltype(auto) z = x; // z的类型是const int,保留了const限定符

 0x06.小心引用和指针的推导

当使用auto推导引用或指针类型时,要确保初始化表达式也是引用或指针,以避免意外的类型推导。

int x = 10;  
int& ref = x;  
auto a = ref; // a的类型是int,不是int&  
auto& b = ref; // b的类型是int&,正确推导为引用  
  
int* ptr = &x;  
auto c = ptr; // c的类型是int*,不是int**  
auto* d = ptr; // d的类型是int*,正确推导为指针

 0x07.初始化表达式中的类型转换

如果初始化表达式涉及类型转换,auto将推导转换后的类型。

double d = 3.14;  
auto e = static_cast<int>(d); // e的类型是int,因为进行了静态类型转换

0x08.与模板结合使用时的小心

在模板编程中,auto可以用于类型推导,但要小心模板参数的类型推导和auto的交互。

template<typename T>  
void func(T x) 
{  
    auto y = x; // y的类型与x相同  
}  
  
int main() 
{  
    func(42); // T被推导为int,y的类型也是int  
    func(3.14); // T被推导为double,y的类型也是double  
}

 4.auto关键字总结

auto关键字在C++中主要用于类型推导,特别是在处理STL容器、Lambda表达式、范围for循环以及复杂类型时,auto可以大大简化代码的编写。然而,过度使用auto可能会降低代码的可读性,特别是在类型信息对于理解代码逻辑至关重要时。因此,在使用auto时,需要权衡代码的简洁性和可读性。

三、基于范围的for循环(C++11)

在C++11中,范围for循环(Range-based for loop)是一项重要的新特性,它提供了一种简洁且高效的方法来遍历容器或数组中的元素。下面将深入探讨这一特性,通过代码和图片详细解释其工作原理和底层实现。

1.范围for的语法

在C++98中如果要遍历一个数组,可以按照以下方式进行

void TestFor()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
	{
		array[i] *= 2;
		cout << array[i] << " ";

	}
	cout<<endl;

	for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
	{
		cout << *p <<" ";
	}
	cout << endl;
}

int main()
{
	TestFor();
	return 0;
}

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因 此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范 围内用于迭代的变量,第二部分则表示被迭代的范围。

void TestFor()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for (auto& e : array)
		e *= 2;
	for (auto e : array)
		cout << e << " ";
}

int main()
{
	TestFor();
	return 0;
}

注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。 

 2. 范围for的使用条件

对于数组而言,就是数组中第一个元素和最后一个元素的范围;

对于类而言,应该提供 begin和end的方法,begin和end就是for循环迭代的范围。

注意:以下代码就有问题,因为for的范围不确定。

void TestFor(int array[])
 {
 for(auto& e : array)
 cout<< e <<endl;
 }

这里传递过来的是数组的首元素地址,并不是数组,它会不知道范围是多少,所以会 报错

不仅如此,并且迭代的对象要实现 ++ 和 == 的操作。(关于迭代器这个问题,以后会讲,现在提一下,没办法讲清楚,现在uu了解一下就可以了)

 3.底层实现原理

// 原始的范围for循环  
for (int x : vec) 
{  
    std::cout << x << std::endl;  
}  
  
// 编译器可能生成的等价代码  
auto it = vec.begin();  
auto end = vec.end();  
while (it != end) 
{  
    int x = *it;  
    std::cout << x << std::endl;  
    ++it;  
}

 4.细节和注意事项

  • 类型推导:范围for循环中的变量类型(如上面的int x)是通过类型推导(type deduction)来确定的。编译器会根据容器或数组中的元素类型来推导变量的类型。

  • 常量性:如果希望遍历过程中不修改容器中的元素,可以将变量声明为常量引用类型,例如const auto& x : vec

  • 范围for循环的限制:范围for循环不能用于修改容器的大小(如添加或删除元素),因为它不提供对迭代器的直接访问。如果需要修改容器,应使用传统的基于迭代器的循环。

  • 数组和容器的兼容性:范围for循环不仅适用于标准容器(如std::vectorstd::list等),还适用于原生数组和C风格的数组。

  • 性能考虑:对于简单的容器和数组,范围for循环的性能与基于迭代器的循环相当。然而,在某些复杂情况下(如需要频繁修改迭代器或进行复杂的条件判断),手动管理迭代器可能会提供更精细的控制和可能的性能优化。

5.范围for总结

总的来说,范围for循环是C++11引入的一个非常有用的特性,它简化了容器和数组的遍历操作,并提高了代码的可读性和可维护性。尽管它在底层是通过编译器转换为基于迭代器的循环来实现的,但这一转换对用户来说是透明的,使得用户能够专注于更高层次的逻辑和算法实现。

 四、指针空值 nullptr(C++11)

在C++编程中,指针是一个非常重要的概念,它允许我们直接操作内存地址。然而,指针的使用也伴随着一定的风险,特别是当指针未初始化或指向无效内存时。为了解决这个问题,C++11引入了一个新的关键字nullptr,以替代传统的空指针常量NULL或整数0。接下来将深入探讨nullptr的底层机制、使用场景以及它如何帮助提高代码的安全性和可读性。

1.nullptr的引入背景

在C++11之前,我们通常使用NULL0来表示空指针。然而,这两种方式都存在一些问题:

  • NULL通常被定义为((void*)0),这是一个类型转换表达式,而不是一个真正的关键字。这可能导致在某些上下文中出现类型不匹配的问题。
  • 使用0作为空指针常量虽然简单,但它与整数字面量0没有区别,这可能导致类型混淆和潜在的错误。

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:

#ifndef NULL
 #ifdef __cplusplus
 #define NULL    0
 #else
 #define NULL    ((void *)0)
 #endif
 #endif

可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何 种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如:

void f(int)
 {
 cout<<"f(int)"<<endl;
 }
 void f(int*)
 {
 cout<<"f(int*)"<<endl;
 }
 int main()
 {
 f(0);
 f(NULL);
 f((int*)NULL);
 return 0;
 }

该程序的本意是想通过 Func(NULL) 调用指针版本的 Func(int*) 函数,

但是由于 NULL 被定义成0,这么一来就不符合程序的初衷了。

在 C++98 中,字面常量 0 既可以是一个整型数字,也可以是无类型的指针 (void*) 常量,

但是编译器默认情况下会将其看成一个整型常量,

如果要将其按照指针方式来使用,必须对其进行强制类型转换 (void*)0 。

为了解决这些问题,C++11引入了nullptr,它是一个类型安全的空指针常量。

2.nullptrNULL的区别

  • NULL是一个宏定义,而不是关键字。它在C++中通常被定义为0((void*)0),这可能导致类型不匹配的问题。
  • nullptr是一个关键字,它的类型是nullptr_t,是一个专门用于表示空指针的类型,与传统的空指针常量NULL(通常被定义为((void*)0)0)不同,nullptr只能被隐式转换为指针类型,而不能被转换为整数或其他非指针类型。这种类型安全性有助于减少类型混淆和潜在的错误。具有类型安全性。

3.nullptr的使用场景

0x01.初始化指针


使用nullptr来初始化指针是一个好习惯,它可以帮助我们避免未初始化指针导致的未定义行为。

int* ptr = nullptr;

0x02.比较指针


使用nullptr来比较指针是否为空,可以提高代码的可读性和安全性。

if (ptr == nullptr) 
{  
    // ptr is null  
}

0x03.函数参数和返回值


在函数参数和返回值中使用nullptr可以明确表示一个指针参数或返回值是可选的或可以为空。

void* allocateMemory(size_t size) 
{  
    if (size == 0) {  
        return nullptr;  
    }  
    // Allocate memory and return pointer  
}

0x05.避免类型混淆


使用nullptr可以避免将整数0误用作指针,从而减少类型混淆和潜在的错误。 

int* ptr = nullptr; // Clear and safe  
// int* ptr = 0; // Less clear and potentially error-prone

 4.注意事项

  • 避免类型混淆:不要将nullptr与整数0混用,以避免类型混淆和潜在的错误。
  • 初始化指针:始终在声明指针时初始化它,即使你暂时不知道它将指向什么。使用nullptr是一个好选择。
  • 检查空指针:在删除指针或访问指针所指向的内存之前,始终检查指针是否为空。
  • 避免悬挂指针:在删除动态分配的内存后,将指针设置为nullptr以避免悬挂指针的问题。
  • 模板中的使用:当将nullptr应用于模板时,模板会将其作为一个普通的类型来进行推导,并不会将其视为T*指针。因此,在模板函数中处理空指针时需要注意这一点。

5.总结

nullptr是C++11引入的一个非常重要的特性,它提高了指针操作的安全性和可读性。通过使用nullptr,我们可以避免类型混淆、减少潜在的错误,并编写更清晰、更健壮的代码。因此,在C++11及更高版本中,我们应该优先使用nullptr来替代传统的空指针常量NULL或整数0

 



 本篇博客到此结束,如有错误之处,望各位指正~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flask项目框架搭建

目录结构 blueprints python包&#xff0c;蓝图文件&#xff0c;相当于路由组的概念,方便模块化开发 例如auth.py文件 from flask import Blueprint, render_templatebp Blueprint("auth", __name__, url_prefix"/auth")bp.route("/login") d…

李沐 X 动手学深度学习 深度学习介绍 学习笔记

x轴是不同的模式&#xff1a;符号学---概率模型---机器学习y轴是我们想做的东西&#xff08;问题领域&#xff09;&#xff1a;感知&#xff08;了解这是什么东西&#xff0c;能看见这个物体&#xff09;---&#xff08;做&#xff09;推理&#xff08;基于我看到的东西想象未来…

揭秘猫咪掉毛的真实原因有哪些?掉毛飞毛宠物空气净化器来救援!

作为三猫家庭&#xff0c;日常家里的毛发、异味一直是困扰我很久的难题。最近窗外的世界柳絮满天飘&#xff0c;家里猫毛满飞&#xff0c;养猫家庭应该都不陌生吧&#xff0c;鼻子嘴巴甚至是眼睛里总感觉有猫毛。不管猫砂换的多勤快&#xff0c;也总能闻到阵阵臭味&#xff01;…

【git】git add时warning:LF will replaced by CRLF

git add时warning&#xff1a;LF will replaced by CRLF 一&#xff0c;问题现象二&#xff0c;问题原因&解决方法 一&#xff0c;问题现象 二&#xff0c;问题原因&解决方法 这个警告的原因是 Git 在进行文件添加操作时&#xff0c;发现行尾结束符不一致。 在不同的…

Klick‘r3.0.4 |智能自动点击,高效省力

Klick’r 是一款专为 Android 设计的开源自动点击工具&#xff0c;能识别屏幕上的图像并进行相应操作。支持游戏中的自动点击、应用测试及日常任务自动化。 大小&#xff1a;27M 百度网盘&#xff1a;https://pan.baidu.com/s/1881Zfevph6_2Zhdc-H_R4A?pwdolxt 夸克网盘&…

定点数和浮点数的详细介绍(一)定义、范围、位宽

1.定点数 1.1定点数描述 定点数包括定点小数(纯小数)、定点整数(纯整数)、整数和小数位数固定的实数。 1.2定点小数: 小数点默认在符号位后面,首位为符号位,其他为数值位(在用二进制代表小数时,例如0xFF,就表示0.5+0.25+0.125+0.0625+0.03125........) 例如,用…

【p2p、分布式,区块链笔记 UPNP】: Libupnp的线程池简述

线程池在网络编程中是一个关键的组成部分&#xff0c;尤其是处理高并发请求时&#xff0c;线程池可以显著提高系统的性能和资源利用效率。它的关键组成部分包括以下几个要素&#xff1a;任务队列&#xff1a;一个&#xff08;或多个&#xff09;用于存放待执行任务的队列。任务…

简单花20分钟学会top 命令手册 (linux上的任务管理器)

1. 介绍 top 是一个常用的 Linux 命令行工具&#xff0c;用于实时监视系统资源和进程的运行情况。用户可以通过 top 命令查看系统的 CPU 使用率、内存占用情况、进程列表等重要信息&#xff0c;帮助快速了解系统运行状态并进行性能监控。该工具可以认为相当于windows上的任务管…

什么是MAC地址?有必要隐藏MAC地址吗?

你是否曾经停下来思考&#xff0c;每当你上网时&#xff0c;你的数字足迹可能会泄露你的个人信息&#xff1f;可能你会问&#xff0c;MAC地址是什么&#xff1f;简单来说&#xff0c;每台联网的电脑MAC地址都是独一无二的&#xff0c;就像是你设备在网络世界中的身份证。它能帮…

MySQL多表查询案例

先看我的表数据 dept表 emp表 salgrade表 student表 course表 student_course表 1. 查询员工的姓名&#xff0c; 年龄&#xff0c; 职位&#xff0c; 部门信息&#xff08;隐式内连接&#xff09; -- 表&#xff1a;emp&#xff0c; dept -- 连接条件 emp.dept_id dept.id …

那些年,我们一起追过的函数:揭秘数学世界里的‘网红’们

在数学中&#xff0c;函数是一种特殊的关系&#xff0c;它将一个集合中的每个元素&#xff08;称为自变量或输入&#xff09;映射到另一个集合中的唯一元素&#xff08;称为因变量或输出&#xff09;。根据函数的性质和定义域、值域的不同&#xff0c;可以将函数分为多种类型。…

七氟烷麻醉药市场研究:未来几年年复合增长率CAGR为4.2%

七氟烷是一种吸入麻醉剂&#xff0c;用于在外科手术过程中诱导和维持全身麻醉。七氟烷是一种挥发性麻醉剂&#xff0c;常用于在外科手术过程中诱导和维持全身麻醉。它因起效快和作用消失快而受到青睐&#xff0c;是成人和儿科患者的理想选择。七氟烷通常通过吸入起作用&#xf…

如何使用Colly库进行大规模数据抓取?

在互联网时代&#xff0c;数据的价值日益凸显&#xff0c;大规模数据抓取成为获取信息的重要手段。Go语言因其高效的并发处理能力&#xff0c;成为编写大规模爬虫的首选语言。Colly库作为Go语言中一个轻量级且功能强大的爬虫框架&#xff0c;能够满足大规模数据抓取的需求。本文…

开源 Three.js 案例及入门教程分享

更多three.js学习资料分享https://www.wjx.cn/vm/OaQEBVS.aspx# 01.Three.js 雨和屋顶 在线预览&#xff1a; https://codepen.io/prisoner849/full/yLWMLjK 源码&#xff1a; https://codepen.io/prisoner849/pen/yLWMLjK 02.Three.js 有趣的 3D 航行 源码&#xff1a; …

【动态网站资源保存下载】

文章目录 概要解决思路技术细节小结 概要 我们在网上浏览网站时&#xff0c;经常有这样的需求&#xff1a;将浏览的网页保存下来&#xff0c;即使无网的情况下也可以继续浏览。比如一些教育类网站的PPT&#xff0c;内容为HTML格式的&#xff0c;无法作为PPT格式下载下来&#…

鸿蒙NEXT开始公测,哪些机型可以升级?鸿蒙版微信界面简洁

华为 Harmony OS NEXT 于10月8日正式开启公测&#xff0c;对鸿蒙 NEXT 系统感兴趣&#xff0c;想要第一时间尝鲜鸿蒙系统的话&#xff0c;千万不要错过本篇文章&#xff01; 哪些手机可以参与鸿蒙 NEXT 公测&#xff1f; 首批参与鸿蒙 NEXT 公测的机型有华为 Mate 60 系列、华…

大型企业的云容器和javaee的关联技术

目前在企业中&#xff0c;尤其是大型互联网企业中&#xff0c;云容器越来越重要&#xff0c;原因是&#xff1a;云容器的架构能够提供一整套的&#xff0c;自动提交&#xff0c;自动打包&#xff0c;自动部署&#xff0c;自动重启&#xff0c;动态配置的解决方案 云容器的整体结…

21亿收官,2024年国庆档没有抱怨市场的资格

截至10月7日晚上8点&#xff0c;2024年国庆档票房已接近21亿大关&#xff0c;但成绩基本定格于此&#xff0c;较去年减少了7亿&#xff0c;回落至2018年水准。 在经历了暑假档票房较去年大幅下滑、中秋档票房回归至2014年水平后&#xff0c;国内电影市场对于国庆档表现出一种复…

【Fine-Tuning】大模型微调理论及方法, PytorchHuggingFace微调实战

Fine-Tuning: 大模型微调理论及方法, Pytorch&HuggingFace微调实战 文章目录 Fine-Tuning: 大模型微调理论及方法, Pytorch&HuggingFace微调实战1. 什么是微调(1) 为什么要进行微调(2) 经典简单例子&#xff1a;情感分析任务背景微调 (3) 为什么微调work, 理论解释下 2…

《2024世界机器人报告》:中国为全球最大市场

国际机器人联合会&#xff08;IFR&#xff09;在9月24日最新发布的《世界机器人报告》中表示&#xff0c;全球有约428万台机器人在工厂运行&#xff0c;同比增长10%。工业机器人年安装量连续第三年超过50万台&#xff0c;在2023年新部署的工业机器人中&#xff0c;有70%在亚洲&…