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

三、The C in C++

第三章主要讲解了 C++ 中继承自 C 语言的核心元素,包括函数创建、执行控制、操作符、数据类型、作用域、存储指示、复合类型创建等。

3.1 创建函数(Creating Functions)

  • C++允许函数重载,同名的函数可以根据参数类型和数量区分:
int add(int x, int y, int z);
int add(float,float,float);
void add();
  • 函数可放入自己的函数库,构成.h.lib 文件,方便重复使用和分布。

3.2 控制程序的执行流程(Controlling execution)

  • 分支:if-else,switch-case
  • 循环类型:while,do-while,for
  • 特殊操作:break 中断循环,continue 跳过本轮继续
  • 递归:函数自己调用自己

3.3操作符

  • 一元操作符:++,–,,&
  • 二元操作符:+ - * / % = == != && || << >>
  • 其他:?: 条件操作符,sizeof
  • 进行计算时应使用括号明确进体顺序,避免误解

3.4 数据类型简介

基本类型:bool, char, int, float, double, void

指针:用于存放地址,需指明指向的类型

#include <iostream>
using namespace std;
int dog,cat,bird;
void f(int pet) {cout << "pet id number:" << pey << endl;}
void main(){int i,j;cout << "f(): " << &f << endl;//produce the addresscout << "dog: " << &dog << endl;cout << "cat: " << &cat << endl;cout << "bird: " << &bird << endl;cout << "i: " << &i << endl;cout << "j: " << &j << endl;int *p = new int;cout << "p: " << &p << endl;cout << "&(*p) :" << &(*p) << endl;//cout << "&(*p)" << p << endl delet p;
}

output:

由此可见

f()的地址在代码段/文本段,属于静态分配

dog,cat,bird,全局变量地址,地址相邻,分配在静态区(BSS段)

i、j, 局部变量,地址较低,且和全局变量区分明显,属于栈区,且高地址向低地址增长

&p , 局部变量int * p本身的地址,也是栈区

&(_p) , 动态分配的int 类型变量地址(通过*_new int),属于堆区

引用:变量的别名,必须初始化,不可重新指向

int a=3,b=5;
int& m = a;//OK
int& m; // error
int& m = b;//ok
int&k = m;
int n = m;
int*p = &m;
int*& ref = p;
m = m+5

引用仅仅只是一个别名,就像m,k它们和a指向同一个位置,占用同一个内存

参数传递:分为值传递、地址传递、引用传递

int i = 10;
int *p = &i;
void* vp = p;//OK
int *ip = vp;//error

其他指针赋值给void*,但是不可以void*赋值给其他型

比较Argument Passing(Value,pointer,reference)

Pass by value

//C03:PassByValue.cpp
#include <iostream>
using namespace std;
void f(int a){cout << "a=" << a << endl;a = 5;cout << "a=" << a << endl;
}
void main(){int x = 47;cout << "x=" << x << endl;f(x);cout << "x=" << x << endl;
}

输出:

x = 47
a = 47
a =  5
x = 47

Pass by address

//C03:PassAddress.cpp
#include <iostream>
using namespace std;
void f(int *p){cout << "p=" << p << endl;cout << "*p=" << *p << endl;*p = 5;cout << "p=" << p << endl;
}
void main(){int x = 47;cout << "x=" << x << endl;cout << "&x=" << &x << endl;f(x);cout << "x=" << x << endl;
}

Pass reference

//C03:PassReference.cpp
#include <iostream>
using namespace std;
void f(int& a){cout << "a=" << a << endl;a = 5;cout << "a=" << a << endl;
}
void main(){int x = 47;cout << "x=" << x << endl;f(x);cout << "x=" << x << endl;
}

比较swap1(Value),swap2(address),swap3(reference)

Passing by Value

#include <iostream>
using namespace std;
void swap1(int x,int y){int temp;temp = x;x = y;y = temp;cout << "x=" << x << "," << "y=" << y << endl;
}
void main(){int a(5),b(9);swap1(a,b)//swap1(5,9);ok?cout << "a:" << a << "," << "b:" << b << endl;
}

问题swap1(5,9);ok?

OK。在 C++ 中,函数参数如果是值传递(pass by value),你完全可以传入常量字面值(如 5, 9),因为:

  • int x, int y值传递:函数内会把参数值拷贝一份到局部变量中;
  • swap1(5, 9) 等价于:x = 5; y = 9; —— 合法;
  • 虽然 xy 在函数中交换了,但这些交换并不会影响外部实参。

Passing by address

#include <iostream>
using namespace std;
void swap2(int* x,int* y){int temp;temp = *x;*x = *y;*y = temp;cout << "X = " << *x << "," << "y=" << *y << endl;
}
int main(){int a(5),b(9);swap2(&a,&b);//swap2(&5,&9);?cout << "a=" << a << "," << "b:" << b << endl;return 0;
}

output:
image-20250414222749330

问题swap2(5,9);ok?

不OK。 函数参数是两个 int,也就是指向整型的指针,因此必须传入 **地址(address)。 然而 **59 是整型字面值(int),不是地址。编译器无法把 int 自动转换成 int(除非你非常暴力地强制类型转换)

Passing by reference

#include<iostream>
using namespace std;
void swap3(int& x,int& y){int temp;temp = x;x = y;y = temp;cout << "x=" << x << "," << "y=" << y << endl;
}
int main(){int a(5),b(9);swap3(a,b);//swap3(5,9);?cout << "a=" << a << "," << "a=" << a << endl;
}

output

image-20250414222441323

问题swap3(5,9);ok?

不OK。这是引用传递(pass by reference),也就是说:

  • 必须传入变量,因为函数参数会变成这些变量的别名(reference)
  • 59常量值不是变量,不能作为引用参数;
  • 引用必须引用一个 具名对象(L-value),但 59R-value(右值),没有地址可引用;

Summary of Argument Passing

image-20250415091158738

3.5 作用域(Scoping)

3.5.1变量只能在其归属作用域内进行操作

void main(){int scp1;//scp1 visible here{	//scp1 still visible hereint scp2;//scp2 visible here{//scp1 & scp2 still visible hereint scp3;//scp1,scp2&scp3 visible here}//<<--scp3 destoryed here//scp3 not available here//scp1 & scp2 still visible here}//<<--scp2 destoryed here//scp3 & scp3 not available here
}//<<--scp1 destoryed here
  • C++ allows you to define variable anywhere in a scope,so you can define a variable right before you use it
  • It reduces the errors you get from being forced to jump back and forth within a scope
  • 大括号定义一个新作用域
  • C++ 允许在任意作用域内定义变量,更加灵活

3.6存储分配指示(Specifying storage allocation)

3.6.1 全局变量(Global variables)

  • Global variables are defined outside all function bodies and are available to all parts of program.
  • Global variables are unaffected by scopes and are always available.
  • If the existence of a global variable in one file is declared using the extern keyword in another file,the data is available for use by the second file.
//C03:Global.cpp
//Demonstration of global variables
#include <iostream>
using namespace std;
int globe = 0;
void func();
void main(){globe = 12;cout << globe << endl;func();//Modify globecout << globe << endl;
}//C03:Global2.cpp
//Accessing external global variables
extern int globe;
//The linker resolves th reference
void func(){globe = 47;
}

output:

image-20250415101540757


//C03:Global.cpp
//Demonstration of global variables
#include <iostream>
using namespace std;
int globe = 0;
void func();
void main(){int globe = 12;cout << globe << endl;func();//Modify globecout << globe << endl;
}//C03:Global2.cpp
//Accessing external global variables
extern int globe;
//The linker resolves th reference
void func(){globe = 47;
}

output:

image-20250415102024115

原因解释

  • main() 中定义的int globe = 12;屏蔽了全局的globe
  • func()修改的是全局的globe,但main()中打印的是局部的
  • 因此即使func修改了全局变量,main中的输出仍为局部值12

3.6.2局部变量(Local variables)

  • Local variables are often called automatic variables because they automatically come into being when the scope is entered and automatically go away when the scope closes.

void func(){

int globe = 47;

}

3.6.3Static variables

  • If you want a value to be persistent(持久的) throughout the life of a program,you can define a function’s local variable to be static and give it an initial value.
  • The initialization is performed only the first time when the function is called,and the data retains(保留) its value between function calls.
  • A static is unavailable outside the scope of the function
//C03:Static.cpp
//Using a static variable in a function
#include <iostream>
using namespace std;
void func(){static int i = 0;//int the functioncout << ++i << ",";
}
void main(){for (int x = 0;x<5;x++){func();}//cout i;//error
}

output:

image-20250415105229247


//C03:FileStatic.cpp
//File scope demonstration.Compiling and
//lingking this file with FileStatic2.cpp
//will cause a linker error
//File scope means only available in this file;
static int fs = 0;
void main(){fs = 1;
}//C03:FileStatic2.cpp
//Trying to references fs
extern int fs;//linker error
void func(){fs = 100;//error
}

3.6.4Extern & linkage

Extern

  • The extern keyword tells the compiler that a variable or a function exists,even if the compiler hasn’t yet seen it in the file currently being compiled.
  • This variable or function may be defined in another file or further down in the current file.

linkage

  • In an executing program,and identifier is represented by storagefont> in memory that holds a variable or a compiled function body.
internal linkage
  • internal linkage means that storage is created to represent the identifier only for the file being compiled.

storage is created to represent the identifier意思是标识符所代表的数据在内存中的位置

  • internal linkage在C++中通过keyword static 实现
external linkage
  • external linkage means that a single piece of storage is created to represent the identifier for all files being compiled.(即非static的全局变量,全局函数)
  • 在所有函数之外定义的变量,以及函数定义,默认具有external linkage。你可以同过static关键字强制将其转为internal linkage,也可以通过extern关键字显示声明其为external linkage.
  • 局部变量只在函数调用期间暂时存在于stack上。linker(链接器)无法识别自动变量(即局部变量),因此它们没有连接属性(no linker)。
//C03:FileStatic.cpp
//internal linkage and external linkage
//linking this file with FileStatic2.cpp
static int fs = 0;//in the file
static void f(){};
int fe = 0;
extern void func(){};
void main(){fs = 1;func();
}//FileStatic.cpp
extern int fs;//linker error
extern int fe;
extern void f();//linker error
void func(){//fs = 100;//errorfe = 100;//f();//error
}

3.6.5常量(Constants)

  • #define PI 3.14159//这是一个replacement 并非Constants

    //Its scope is: from #define to #undef

  • const double PI = 3.14159; //const

  • const是一个实际变量,但值不可变

  • const必须有一个初始化的值

void f(const int a){};
int main(){f(5);              // 调用 f 函数,传入字面值 5
}

这是可行的


3.6.6 volatile

  • Whereas(尽管) the qualifier(修饰符) const tells the compiler “This never changes”(Which allows the compiler to perform extra optimizations).
  • 修饰符volatile则告诉编译器“你永远不知道这个值什么时候会改变” ,并且禁止编译器基于该变量的稳定性进行任何优化

3.7操作符与用法(Operators and their use)

3.7.1赋值(Assignment)

A = 4;

  • A:an lvalue(左值),a distinct,named variable
  • 4:an rvalue(右值),a constant,variable,or expression that can produce a value

3.7.2 数学的操作符(Mathematical operators)

  • addition(+)
  • subtraction(-)
  • division(/)
  • multiplication(*)
  • modulus(%):this produces the remainder(余数) from integer division.

3.7.3 关系运算符(Relational operators)

  • <,>,<=,>=,==,!=
  • 这些运算符产生bool值,就像C语言一样
  • 1 for true,0 for false.

3.7.4 逻辑操作符(Logical operators)

  • &&,||,|,!
  • The result is true if it has a non-zero value,and false if it has a value of zero.

3.7.5按位操作符(Bitwise operators)

  • bitwise and (&)
  • bitwise or (|)
  • bitwise not /complement (~)//补码
  • bitwise exclusive or / xor (^)//异或
  • &=;|=;^=

3.7.6移位操作符(Shift operators)

  • left-shift (<<)
  • right-shift (>>)
  • <<= ; >>=

3.7.7一元操作符(Unary operators)

  • Bitwise not (~)
  • logical not (!)
  • unary minus (-) ; unary plus (+)
  • increment (++); decrement (–)
  • address-of (&)
  • dereference (& and ->)//间接引用
  • cast
  • new;delelte

3.7.8三元操作符(The ternary operator)

  • c=a>b ? a : b

    if (a> b ) c = a;

    else c = b;


3.7.9 逗号运算符(The comma operators)

//C03:CommaOperator.cpp
#include <iostream>
using namespace std;
void main(){int a =0,b=1,c=2,d=3,e=4;a = (b,c,d,e);cout << "a=" << a << endl;//The parentheses(圆括号) are critical here.Without//them,the statement will evaluete to.(a = b),c,d,e;cout << "a=" << a << endl;
}

output:

image-20250415144033623

原因解释:

a = (b,c,d,e);

  • 逗号表达式 (x, y)先执行 x,再执行 y,并返回 y 的值
  • 所以a = (b, c, d, e); 实际含义是:a = e。
  • 也就是逗号表达式(b,c,d,e) 会,顺序执行b,c,d,e这些表达式,最终只返回最后一个表达式e的值
  • 所以a只赋值了一次:a = e;

(a = b),c,d,e;

  • 它不是赋值语句(它不是a = (……)
  • 而是一个逗号表达式序列,主作用是执行它里面的每个子表达式,并返回最后一个表达式的值。
  • 其中(a = b)起到赋值操作,将b的值赋给a
  • 然后剩下的c,d,e都是无副作用的值表达式,被执行但不改变任何东西
  • 所以最后a = 1

3.7.10 表达式里常出的错误(Common pitfalls when using operators)

= ==

&& &

|| |

//C03:Pitfall.cpp
void main(){int a = 1,b = 1;while (a = b)//error{……}
}

3.7.11类型转换操作符(Casting operators)

  • Casting allows you to make this type conversation explicit

  • (type name) value

  • type name (argument)

    ​ int a = 100;

    ​ float b = float(a)

    ​ float c = (float) a

    ​ int d = int (5.5);


3.7.12 C++ explicit casts

  • static_cast<Type> (e): 用于在相关类型之间进行转换。

    static_cast<int\>(5.5);

  • reinter_cast<Type>(e): 处理不相关类型之间的转换,比如指针类型之间的“强制解释”。

    int *p = reinterpret_cast<int*\>(0x12345678);

    🚨 非常危险,常用于底层编程。

  • const_cast<Type>(e): 去掉变量的 const 限定。用于把 const 对象转换为非常量对象(⚠谨慎使用)

    const int*p = ……;

    int *q = const_cast<int*\>(p);

  • dynamic_cast<Type>(e): 在运行时进行类型检查的转换。通常用于多态类之间的类型安全向下转换。

    Base* bp = new Derived();
    Derived* dp = dynamic_cast<Derived*>(bp); // 如果 bp 不是 Derived*,则返回 nullptr


3.7.13 sizeof操作符

#include <iostream>
using namespace std;
void main(){cout << "bool:" << sizeof(bool) << endl;cout << "char:" << sizeof(char) << endl;cout << "int:" << sizeof(int) << endl;cout << "float:" << sizeof(float) << endl;cout << "double:" << sizeof(double) << endl;cout << "long double:" << sizeof(long double) << endl;
}

output:

image-20250415151025842

结果可能会因为不一样的编译系统而不一样


3.7.14 asm关键字

  • 你可以在C++程序中编写针对硬件的汇编代码
  • 编写汇编语言时需要使用的具体语法依赖于(编译器)。

3.7.15显示操作符(Explicit operators)

  • These are keywords for bitwise and logical operators.(Not all complier(编译器) can support them )

  • and : && (logical and)

    or : || (logical or)

    not : ! (logical NOT)

    not_eq: != (logical not-equivalne)

    bitand: & (bitwise and)

    and_eq: &= (bitwise and-assignment)

    bitor: | (bitwise or)

    or_eq: |= (bitwise or-assignment)

    xor: ^ (bitwise exclusive-or)

    xpr_eq: ^= (bitwise exclusive-or-assignment)

    compl:~ (ones complement)


3.8复合类型创建(Composite type creation)

简述

  • C++ 提供工具,允许你组合(compose)基础数据类型,从而创建更复杂的数据类型。
  • 其中最重要的是结构体(struct),它是C++中**类(class)**的基础

3.8.1使用typedef创建别名(Aliasing names with typedef

  • typedef existing-type alias-name

    typedef int* IntPtr;

    IntPtr x,y;


3.8.2使用struct组合变量(Combining variables with struct)

  • A struct is a way to collect a group of variables into a structure.
  • The struct is the foundation for the class in the C++.
//C03:SimpleStruct.cpp
struct Structure1{char c;double b;
};
int main(){Structure1 s1,s2;Structure1* p = &s2;s1.c = 'a';//Select an element using a '.'s1.d = 0.00093;p->c = 'b';//Select an element using a '->'p->d = 10.5;return 0;
}

3.8.3使用enum澄清程序(Clarifying programs with enum

  • An enumeration is a type that can hold a set of values specified by the user.

    enum name{ASM,AUTO,BREAK}

  • By default(默认) ,the values of enumerators(枚举值) are initialized increasing from 0

    ASM = 0,AUTO = 1,BREAK = 2

  • An enumerator(枚举值) can be initialized by a constant-expression of integral type(整型常量表达式)

    ASM = 1,AUTO = 5;这里这样写完后,BREAK就会默认为AUTO+1,所以BREAK = 6

  • It is used less in C++.(在C++中使用较少)


3.8.4使用union节省内存(Saving memory with union)

  • Sometimes a program will handle different types of data using the same variable.
  • A struct contains all the possible different types you might need to store.但是使用struct 时,每个成员都有独立的内存空间。
  • An union is a special type of a class,where every member has the same address(每个成员共用同一个地址)
union A{int a;double b;
};
A x;

image-20250415185058288


3.8.5 数组(Arrays)

概述
  • T[size]表示“由sizeT类型元素组成的数组”。

  • The elements are indexed from 0 to size-1(元素索引范围)

  • There is no array assignment. (数组不能直接赋值)

    意思就是说在C++中,不能把一个数组整体赋值给另一个数组

    int a[3] = {1,2,3};
    int b[3];
    b = a;//错误!不能直接赋值数组
    

    原因:这是因为在C++中,数组名其实代表的时数组的首地址(在下文会提到),不是一个可以整体赋值的“对象”。并非是平常所理解的变量

  • The name of an array is the starting address of the array.

  • Initialization:

    int v1[4] = {1,2,3,4};
    char v2[] = {'a','b','c','\0'};
    char v3[2] = {'a','b','\0'};//error 不可以超出数组size
    char v4[3] = {'a','b','c','\0'};//ok
    int v5[8] = {1,2,3,4};//部分初始化,未初始化的会系统默认初始化为0
    

    注意事项:char v[3] = {'a','b','c'};是字符数组,这样编写不会报错,但它由于缺少’\0’,所以并不是一个字符串,如果执行cout << v;,程序将会崩溃,因为cout认为它是一个字符串,但它没有\0来标记结束。

    image-20250415190838378

Pointer and arrays
  • The name of an array can be used as a pointer to its initial elements.

  • Access a array can be achieved either through a pointer to an array plus an index or through a pointer to an element.

  • 注意:大多数C++实现不会对数组访问进行范围检查(即你越界访问不会报错,但会导致未定义行为)。

    int v[] = {1,2,3,4};
    int* p1 = v;//pointer to initial element
    int* p2 = &v[2];
    

    v[2],*(v+2),*(p1+2),*p2都是3


3.9 调式提示(Debugging hints)

3.9.1预处理器调试标志(Pre-processor debugging flags)

这是用#define来控制是否输出调试信息的方式,编译时决定

示例:

#include <iostream>#define DEBUG  // 注释掉这一行可以关闭调试输出int main() {int a = 5, b = 10;#ifdef DEBUGstd::cout << "Debug: a = " << a << ", b = " << b << std::endl;#endifstd::cout << "Sum = " << (a + b) << std::endl;return 0;
}

DEBUG只是一个宏的名字,可以用DEBUG1等等代替

用法说明:

  • #ifdef DEBUG:只有在DEBUG被定义时,才会编译输出的调试代码。
  • 可以用来临时打开/关闭调试信息,不影响主逻辑

3.9.2运行时调试标志(Runtime debugging flags)

这是一种运行时控制调试信息的方式,通常用变量或命令行参数来控制。

示例:

#include <iostream>int main() {bool debugMode = true;  // 运行时控制开关int a = 3, b = 7;if (debugMode) {std::cout << "[DEBUG] a = " << a << ", b = " << b << std::endl;}std::cout << "Product = " << (a * b) << std::endl;return 0;
}

用法说明:

  • 可以通过配置文件、命令行参数等方式改变debugMode
  • 比预处理器方式灵活,不需要重新编译

3.9.3C语言的assert()

这是一个运行时断言,如果**表达式为假(false)**,程序会打印错误信息并终止

示例:

#include <iostream>
#include <cassert>  // 引入 assertint divide(int a, int b) {assert(b != 0);  // 如果 b 为 0,会终止程序return a / b;
}int main() {int result = divide(10, 2);  // 正常std::cout << "Result = " << result << std::endl;result = divide(10, 0);      // 触发断言失败return 0;
}

用法说明:

  • assert()Debug模式(开放时用的编译配置)下启用,在Release 模式(发布程序时用的优化配置)下会被编译器忽略(你可以用-DNDEBUG来关闭它)。
  • 非常适合用于验证前提条件,尤其是在开发测试时。

3.10函数地址(Function address)

概述

  • Once(一旦) a function is compiled and loaded into the computer to be executed,it occupies a chunk(区块) of memory,and has an address.
  • You can use function address with pointers just as you can use variable address.

3.10.1定义函数指针(Defining a function pointer)

  • void (*funcPtr)();表示:funcPtr是一个指向无参数、无返回值函数的指针
  • funcPtr是一个指向函数的指针,该函数没有参数,也没有返回值。

  • void* funcPtr();表示:funcPtr是一个函数,它的返回类型时void*(即返回一个void指针
  • funcPtr是一个返回void*类型的函数(而不是指针

3.10.2复杂的声明与定义(Complicated declarations & definitions)

  • You will rarely(很少) need very complicated declarations and definitions.
  • 逐步分析每一部分,并使用从右往左的规则来理解它。
  • float(*(*fp2)(int,int,float))(int)
  • fp2是一个指向函数的指针,这个函数接受三个参数(int,intfloat),并返回一个指向另一个函数的指针。
  • 那个被返回的函数接受一个int参数,返回一个float值。

3.10.3使用函数指针(Using a function pointer)

  • Once you define a pointer to a function,you must assign it to a function address before you can use it.
  • The function name func denotes(表示) the address of a function func().
//C03.PointerToFunction.cpp
//Defining and using a poinnter to a function
#include <iostream>
using namespace std;
void func(){cout << "func() called" << endl;
}int main(){void (*fp)();//Delare a function pointerfp = func;   //Point to a function(*)fp();     //Call the function,func();void (*fp2)() = func;   //Define and initialize(*fp2)();               //Call the functionreturn 0;
}

3.11动态存储分配(Dynamic storage allocation)

  • **new/new[]😗*creates dynamic objects.

    • new type(initialize); // individual object
    • new type[size]; //array
  • new/new[] returns a pointer that pointer to type.

  • new[]dose not initialize the memory returned.

    使用 new[] 创建数组时,不会自动初始化数组里的元素

  • **delete/delete[]😗*destroy dynamic object.

    • delete pointername; // individual
    • delete[] pointername; // array
  • An object created by new must be destroyed by delete.

  • A pointer can be destroyed by delete/delete[] only once.

#include <iostream>
using namespace std;
int main(){int *p;p = new int(5);   //individual obejctcout << *p << endl;delete p;        //destory individual objectp = new int[5];   //arrayfor (int i = 0 ; i < 5 ; i++)*(p+i)=i;for (int i = 0 ; i < 5 ; i++)cout << *(p+i) << "\t";delete[] p;      //destroy arrayreturn 0;
}

output:

image-20250415202723513


3.12 Summary

  • Pointers
  • References
  • Operators : Casting operators
  • Scope
  • Const
  • Static,extern
  • New,delete

相关文章:

  • TV板卡维修技术【一】
  • 什么是GOTS认证,GOTS认证有什么要求?GOTS认证有什么作用
  • 基于动态注意力机制与双向融合的目标检测模型详解
  • 【树莓派 PICO 2 测评】采集 DS18B20 数据及 OLED 显示
  • Dockerfile项目实战-单阶段构建Vue2项目
  • vue动画
  • 索引语法SQL性能分析索引的使用
  • 依赖注入(DI)与自动装配:本质就是“赋值“吗?
  • PBKDF2全面指南(SpringBoot实现版)
  • AI agents系列之智能体框架介绍
  • Docker华为云创建私人镜像仓库
  • K-均值聚类机器学习算法的优缺点
  • C++第三方库【JSON】nlohman/json
  • CefSharp浏览器(AntdUI.Tabs)标签页关闭时资源释放ChromiumWebBrowser示例源码
  • 【文献笔记】LLM-based and retrieval-augmented control code generation
  • SmolVLM新模型技术解读笔记
  • 联邦学习与协作学习:数据隐私与模型协同进化的未来之路
  • 在SpringBoot中访问 static 与 templates 目录下的内容
  • 在 MySQL 单表存储 500 万数据的场景下,如何设计读取
  • 冲刺高分!挑战7天一篇nhanes机器学习SCI!DAY1-7
  • 观察丨微短剧盛行“拿来主义”,版权保护迫在眉睫
  • 天工机器人获首个人形机器人半马冠军
  • 真实体验不同价值观和生活方式,小鹿、仁科都要上这档节目
  • 中超浙江队外援布彭扎意外坠楼身亡,加蓬总统发布讣告
  • 共享单车、公共设施表面等频现“小广告”?上海将出手治理
  • 光明日报:“拒绝上学门诊”一号难求,治本药方或在医院外