C++日新月异的未来代码:C++11(下)

C++集成HuggingFace模型实战:llama.cpp与GGUF格式应用指南 在AI模型部署领域,将预训练模型集成到原生C++应用是追求高性能与低资源占用的关键技术路径。其核心原理在于通过模型格式转换与专用推理引擎,实现脱离Python依赖的本地化推理。这一技术方案的价值在于为桌面应用、嵌入式系统和游戏引擎等场景提供毫秒级响应与精细硬件控制能力。应用场景广泛覆盖边缘计算、实时推理与资源受限环境。本文聚焦于使用llama.cpp与GGUF格式,通过模型转换、内存映射与量化技术,解决C++调用HuggingFace模型的实际工程挑战,并深入探讨分词器集成与性能优化等关键环节。 阅读详情
AI摘要

本文接上篇继续介绍C++11常用新特性。涵盖lambda表达式,包括引入、语法、使用和本质;类的新增语法,如移动构造、default和delete关键字;可变参数模板,涉及概念、获取个数、展开方法等;包装器,包含function和bind的使用,提升模板效率。

接上篇,继续学习C++11的常用新特性

1.lambda表达式

1.1 引入

lambda 表达式是一种匿名函数对象,允许在代码中直接定义和使用小型的函数,无需额外定义函数或函数对象类,这么讲,感觉还是太理论了,下面将通过特定场景介绍其使用:

struct Goods
{
	string _name;  // 名字
	double _price; // 价格
	int _evaluate; // 评价
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};

struct ComparePriceLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price < gr._price;
	}
};

struct ComparePriceGreater
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price > gr._price;
	}
};

int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
   3 }, { "菠萝", 1.5, 4 } };
	sort(v.begin(), v.end(), ComparePriceLess());
	sort(v.begin(), v.end(), ComparePriceGreater());
}

日常生活中,一件商品包含多个特性,若想针对某个特性进行排序,那么就需要使用算法库里的 sort,设置自定义类型的比较方式,那么仿函数就是个很好的方式

随着 C++ 语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个 algorithm 算法,都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便。因此,在 C++11 语法中出现了 lambda 表达式

1.2 语法

lambda表达式书写格式:

[capture-list] (parameters) mutable -> return-type { statement }

lambda表达式各部分说明:

  • [capture-list] : 捕捉列表,该列表总是出现在 lambda 函数的开始位置,编译器根据 [] 来判断接下来的代码是否为 lambda 函数,捕捉列表能够捕捉上下文中的变量供 lambda 函数使用

  • (parameters):参数列表,与普通函数的参数列表一致,如果不需要参数传递,则可以连同 () 一起省略

  • mutable:默认情况下,lambda 函数总是一个 const 函数,mutable 可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)

  • ->returntype:返回值类型,用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导

  • {statement}:函数体,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量

🔥值得注意的是: 在 lambda 函数定义中,参数列表和返回值类型都是可选忽略部分,而捕捉列表和函数体可以为空。因此 C++11 中最简单的 lambda 函数为:[]{}; 该lambda 函数不能做任何事情

1.3 使用

int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
   3 }, { "菠萝", 1.5, 4 } };
   
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {
		return g1._price < g2._price; });
		
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {
		return g1._price > g2._price; });
		
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {
		return g1._evaluate < g2._evaluate; });
		
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {
		return g1._evaluate > g2._evaluate; });

	return 0;
}

因此,lambda 表达式可以这样套用在 sort 里,比仿函数确实方便且可观性更高了,可以看出 lambda 表达式实际是一个匿名函数(无名函数),该函数无法直接调用,如果想要直接调用,可借助 auto 将其赋值给一个变量

auto ret = [ ](const Goods& g1, const Goods& g2) {return g1._evaluate < g2._evaluate; }

对于捕捉列表 [],平常一般使用的不多,但是某些情况还是要使用的,需要了解其用法

捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用:

  • [x]:表示值传递方式捕捉变量 x
  • [=]:表示值传递方式捕获所有父作用域中的变量(包括 this )
  • [&x]:表示引用传递捕捉变量 x
  • [&]:表示引用传递捕捉所有父作用域中的变量(包括 this )
  • [this]:表示值传递方式捕捉当前的 this 指针

🔥值得注意的是:

  1. 父作用域指包含 lambda 函数的语句块
  2. lambda 默认以值传递的方式进行,传值捕捉的变量是不可修改的
int main() 
{
    int x = 10;
    auto func = [x]() mutable { x = 20; cout << x << std::endl; };
    func();
    cout << x << endl;
    return 0;
}

使用 mutable 关键字就可以修改了,但是这种修改只是对 lambda 内部的副本进行修改,不会影响到原始的变量。在 main 函数中再次输出 x 时,其值仍为 10

  1. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割,比如:[=, &a, &b],以引用传递的方式捕捉变量 a 和 b,值传递方式捕捉其他所有变量;[&,a, this],值传递方式捕捉变量 a 和 this,引用方式捕捉其他变量
  2. 捕捉列表不允许变量重复传递,否则就会导致编译错误
  3. 在块作用域以外的 lambda 函数捕捉列表必须为空,在全局作用域中,并没有局部变量可供 lambda 函数捕获
  4. 在块作用域中的 lambda 函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错
  5. lambda 表达式之间不能相互赋值,即使看起来类型相同,但是可以拷贝构造(每个 lambda 表达式都有其独特的、未命名的类型。即使两个 lambda 表达式的参数列表和返回类型相同,它们的类型也是不同的)

1.4 本质

在这里插入图片描述

转到反汇编可以发现,其实 lambda 的本质就是被包装的仿函数,编译器会自动生成一个类,在该类中重载了 operator()

2.类的新增语法

2.1 移动构造、移动赋值运算符

C++11 新增了两个:移动构造函数和移动赋值运算符重载,在上一篇有进行详细的说明

传送门:C++日新月异的未来代码:C++11(上)

  • 如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,如果实现了就调用移动构造,没有实现就调用拷贝构造

  • 如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造完全类似)

  • 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值

2.2 default

class Person
{
public:
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}
	
	Person(const Person& p)
		:_name(p._name)
		, _age(p._age)
	{}
	
	Person(Person && p) = default;
private:
	bit::string _name;
	int _age;
};

int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = std::move(s1);
	return 0;
}

default 是强制生成默认函数的关键字,我们提供了拷贝构造,就不会生成移动构造了,那么我们可以使用 default 关键字显示指定移动构造生成

2.3 delete

class Person
{
public:
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}
	
	Person(const Person& p) = delete;
private:
	bit::string _name;
	int _age;
};
int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = std::move(s1);
	return 0;
}

delete 是禁止生成默认函数的关键字,当类显式删除了拷贝构造函数时,编译器不会自动生成移动构造函数(即使没有显式删除移动构造函数),代码中没有显式定义移动构造函数,且隐式移动构造函数被禁用,因此无法完成移动初始化

🔥值得注意的是:

移动构造函数的核心目的是高效转移资源所有权(如动态内存、文件句柄等),而拷贝构造函数的目的是创建资源的独立副本。如果一个类禁用了拷贝构造函数,通常意味着:

  • 资源不可复制: 例如独占式资源,拷贝会导致资源管理混乱
  • 防止意外拷贝: 开发者希望禁止对象的复制操作,强制使用移动语义

此时,如果编译器仍然自动生成移动构造函数,可能会破坏这种设计意图

3.可变参数模板

3.1 概念

在这里插入图片描述

其实可变模板参数早在C语言就已经有了,后面三个点点点就是可变模板参数,比如: printf("%d,%d,%d", x, y, z),后面的参数个数是可以自己控制有多少个的,这就是一种可变模板参数

template <class ...Args>
void ShowList(Args... args)
{}

int main()
{
	ShowList();
	ShowList(1);
	ShowList(1, 2.2);
	ShowList(1, 2, "xxxxx");
	return 0;
}

回到实际定义,Args 是一个模板参数包,args 是一个函数形参参数包,声明一个参数包Args... args,这个参数包中可以包含 0 到任意个模板参数

3.2 获取个数

template <class ...Args>
void ShowList(Args... args)
{
	cout << sizeof...(args) << endl;
}

int main()
{
	ShowList();
	ShowList(1);
	ShowList(1, 2.2);
	ShowList(1, 2, "xxxxx");
	return 0;
}

这个用法也是很奇葩。。。

3.3 展开参数包

不知道当初设计怎么想的,这里想要 for 循环遍历展开是不可行的,编译器不支持,所以这里的展开方法做了解即可

3.3.1 递归函数

// 递归终止函数
template <class T>
void ShowList(const T& t)
{
	cout << t << endl;
}

// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{
	cout << value << " ";
	ShowList(args...);
}

int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', string("sort"));
	return 0;
}

模式匹配: 展开函数 ShowList(T value, Args... args) 匹配 至少一个参数 的情况,每次取出第一个参数 value,剩余参数构成新的参数包 args... ,终止函数 ShowList(const T& t) 匹配仅有一个参数 的情况,结束递归

参数包展开: args... 在递归调用时会被解包,每次减少一个参数,直到参数包为空,
关键语句 ShowList(args...) 会触发模板的递归实例化,直到匹配终止函数

输出顺序: 先打印当前参数 value,再递归处理剩余参数,确保参数按传入顺序输出

3.3.2 逗号表达式

template <class T>
void PrintArg(T t)
{
	cout << t << " ";
}

//展开函数
template <class ...Args>
void ShowList(Args... args)
{
	int arr[] = { (PrintArg(args), 0)... };
	cout << endl;
}

int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', string("sort"));
	return 0;
}

(PrintArg(args), 0)... 会将参数包 args... 展开为多个表达式,打印对应的值,然后返回 0(用于填充数组)

// 原始代码
int arr[] = { (PrintArg(args), 0)... };

// 展开后等价于
int arr[] = { (PrintArg(1), 0), (PrintArg('A'), 0), (PrintArg("sort"), 0) };

PrintArg 的返回值是 void,无法初始化 int 数组,即使 PrintArg 返回参数类型(如 T),参数包可能包含不同类型(如 int, char),仍会导致类型不匹配

每个元素必须是 int 类型,因此需要用 0 作为统一的返回值,保证初始化的数组元素都为相同类型

3.4 emplace系列的接口

int main()
{
	list< pair<int, char> > mylist;
	mylist.emplace_back(10, 'a');
	mylist.emplace_back(20, 'b');
	mylist.emplace_back(make_pair(30, 'c'));
	
	mylist.push_back(make_pair(40, 'd'));
	mylist.push_back({ 50, 'e' });

	for (auto e : mylist)
		cout << e.first << ":" << e.second << endl;
	return 0;
}

emplace_back 的作用和 push_back 相同,但是 mylist.emplace_back(20, 'b') 这种格式的写法更方便一些

其实我们会发现其实差别也不大,emplace_back 是直接构造了,push_back 是先构造,再移动构造,移动构造的消耗很小,其实没啥影响

3.5 可变参数模板的实际应用

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		,_month(month)
		,_day(day)
	{
		cout << "Date构造" << endl;
	}

	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << "Date拷贝构造" << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};


template <class ...Args>
Date* Create(Args... args)
{
	Date* ret = new Date(args...);
	return ret;
}

int main()
{
	list<Date> lt;
	Date d(2023, 9, 27);
	// 只能传日期类对象
	lt.push_back(d);

	// 既能传日期类对象
	// 又能传日期类对象的参数包
	// 参数包,一路往下传,直接去构造或者拷贝构造节点中日期类对象
	lt.emplace_back(d);
	lt.emplace_back(2023, 9, 27);
	return 0;
}

push_back 只能传日期类对象,emplace_back 既能传日期类对象,又能传日期类对象的参数包。参数包,一路往下传,直接去构造或者拷贝构造节点中日期类对象

4.包装器

4.1 function

template<class F, class T>
T useF(F f, T x)
{
	static int count = 0;
	cout << "count:" << ++count << endl;
	cout << "count:" << &count << endl;
	return f(x);
}

double f(double i)
{
	return i / 2;
}

struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};

int main()
{
	// 函数名
	cout << useF(f, 11.11) << endl;
	// 函数对象
	cout << useF(Functor(), 11.11) << endl;
	// lamber表达式
	cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;
	return 0;
}

我们知道函数指针,仿函数,lambda表达式,这三种都是函数对象的创建方式,同时调用这三个方式实例化模板,useF函数模板实例化了三份,明明都是相同的内容,实在是没有必要,会导致模板的效率低下

那么这种时候就需要使用头文件 <functional> 中的 function,function 包装器也叫作适配器。C++中的 function 本质是一个类模板,也是一个包装器

// 类模板原型如下
template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;

模板参数说明:

  • Ret : 被调用函数的返回类型
  • Args…:被调用函数的形参

下面直接修改以上代码,来展示 function 的使用效果:

template<class F, class T>
T useF(F f, T x)
{
	static int count = 0;
	cout << "count:" << ++count << endl;
	cout << "count:" << &count << endl;
	return f(x);
}

double f(double i)
{
	return i / 2;
}

struct Functor
{
	double operator()(double d)
	{
		return d / 3;
	}
};

int main()
{
	// 函数名
	function<double(double)> func1 = f;
	cout << useF(func1, 11.11) << endl;
	// 函数对象
	function<double(double)> func2 = Functor();
	cout << useF(func2, 11.11) << endl;
	// lamber表达式
	function<double(double)> func3 = [](double d)->double { return d / 4; };
	cout << useF(func3, 11.11) << endl;
	return 0;
}

三种可调用对象被统一为同一类型:包装类,模板只实例化一次,静态变量共享(即这个 count 只有一份),

4.2 bind

bind 函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器),接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

bind 可以理解为一个接收包装类的适配器,上面的例子都是直接将函数给到包装类,那么 bind 就是将特定的函数和参数绑定到包装类,通过例子解析会更容易理解:

int Plus(int a, int b)
{
	return a + b;
}

class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};

int main()
{
	//表示绑定函数plus 参数分别由调用 func1 的第一,二个参数指定
	std::function<int(int, int)> func1 = std::bind(Plus, placeholders::_1,
		placeholders::_2);
	//auto func1 = std::bind(Plus, placeholders::_1, placeholders::_2);
	//func2的类型为 function<void(int, int, int)> 与func1类型一样
	//表示绑定函数 plus 的第一,二为: 1, 2
	auto  func2 = std::bind(Plus, 1, 2);
	cout << func1(1, 2) << endl;
	cout << func2() << endl;

	Sub s;
	// 绑定成员函数
	std::function<int(int, int)> func3 = std::bind(&Sub::sub, s,
		placeholders::_1, placeholders::_2);

	// 参数调换顺序
	std::function<int(int, int)> func4 = std::bind(&Sub::sub, s,
			placeholders::_2, placeholders::_1);
	cout << func3(1, 2) << endl;
	cout << func4(1, 2) << endl;
	return 0;
}

bind 的第一个参数传的是函数,后面的是一系列要传的参数,_1 为第一个参数,_2 为第二个参数,以此类推,参数既可以是待定的,也可以是具体的值,placeholders 属于 std 命名空间,若展开了就不用写

在这里插入图片描述

🔥值得注意的是:

  • 若函数是非静态成员函数,必须在 Sub::sub 前加上 &,因为非静态成员函数依赖对象,必须显式调用其地址,普通函数指针直接指向代码地址,而成员函数指针需要同时包含类的类型信息和函数地址,因此还需要将对象 s 传过去

  • 若函数是静态成员函数,和普通函数一样都是全局函数,就不需要加 & 和传对象


希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

Visual C++实战进阶:从开发环境配置到Windows核心编程 C++作为高性能系统编程的核心语言,其价值在于对底层硬件的直接控制和高效率执行。在Windows平台上,Visual C++开发环境提供了与操作系统深度集成的工具链,通过Visual Studio IDE和MSVC编译器,开发者能够构建从桌面应用到系统服务的各类程序。其技术价值体现在对Windows API的完整支持、优秀的运行时性能以及对历史代码的兼容性上,这使得它在游戏开发、工业控制、高性能计算等场景中不可替代。在实际工程中,开发者常面临microsoft visual c++ redistributa 阅读详情

相关推荐

2024年C/C++面试全攻略:从基础项目到高薪Offer

C/C++作为系统级编程的核心语言,其内存管理、并发编程和性能优化等底层原理是构建高性能软件的基础。理解这些概念不仅能提升代码质量,更是应对现代软件开发挑战的关键。在技术价值层面,掌握C++11/14/17新特性如智能指针、移动语义,以及CMake、Git等现代工具链,能显著提高开发效率和项目可维护性。这些技能在嵌入式系统、游戏开发、高频交易等对性能和可靠性要求极高的应用场景中尤为重要。本文以“起风了”音乐播放器项目为例,深入探讨了C/C++程序员在2024年求职面试中需要掌握的核心技能和实战策略,涵盖了从

weixin_31856057的博客 297

C++日新月异的未来代码:C++11(上)

C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个重点去学习

Zero_VPN的博客 3019

C++编程法则365天一天一条(0)了解C++的发展历史

C++ 语言是从C语言发展而来的。 C语言有很多优点,也有很多不足。如对类型匹配的检查不够严格、基本没有支持代码重用的机制、不支持面向对象等。这使得在用C语言开发大规模的软件时,维护和扩充都比较困难。 20世纪70年代中期,Bjarne Stroustrup在剑桥大学计算机中心工作。他使用过Simula和ALGOL,接触过C。他对Simula的类体系感受颇深,对ALGOL的结构也很有研究,深知运行效率的意义。既要编程简单、正确可靠,又要运行高效、可移植,是Bjarne Stroustrup的初衷。以C为背景

二进制君 1217

现代C++探险之旅:趣解C++入门到征服C++11、C++17、C++20(课程下载)

现代C++探险之旅:趣解C++入门到征服C++11、C++17、C++20

软希网分享源码的博客 1881

【UE 反射】反射的原理是什么?如何使用机制?

静态类型检查确保了类型的早期一致性和高效的代码执行,但减少了灵活性。动态类型检查提供了更大的灵活性,但增加了运行时的开销和潜在的错误。反射作为一种动态特性,无论是在静态类型语言还是动态类型语言中,都提供了强大的运行时类型操作能力,但也伴随着性能和安全性方面的权衡。通过理解这些联系,开发者可以在不同的编程语言和应用场景中选择适合的类型检查方式和反射机制,以实现所需的动态行为和灵活性,同时保证性能和安全性。

hhw_hhw的博客 6034

5分钟搞懂基因组规模代谢网络(GSMM):从数据库选择到模型构建全流程

本文详细解析基因组规模代谢网络(GSMM)构建的全流程,从数据库选择到模型优化。重点介绍MetaCyc、BiGG等主流数据库的黄金三角评估法则,对比自上而下与自下而上两种建模方法,并提供模型修剪、仿真优化的实用技巧与避坑指南,帮助研究者高效构建精准代谢网络模型。

weixin_30872157的博客 138

C++ 0x/11学习笔记

今天在看微软提供的windows8的相关开发文档和Sample程序,发现有个C++程序的表达方式完全象天书,查了下,原来是C++0x/11新支持的Lambda表达式,本来一直懒得去看C++0x/11的说明,想等用到再去研究,今天趁这个机会稍微浏览了下,大概整理了如下这些新特性,跟大家分享一下。 稍微吐槽下,C++0x/11是继C++ 03后通过的最新的C++标准库,对C++语法特性和开发库两方面

my_business的专栏 3892

深入解析EDID中Display Descriptor Block的配置技巧与实战应用

本文深入解析EDID中Display Descriptor Block的配置技巧与实战应用。通过剖析像素时钟、有效像素、消隐区与同步脉冲等核心参数,并结合1280x720@60Hz的实战配置案例,指导开发者如何正确为定制硬件或非标准显示器编写“身份证”,避免黑屏、分辨率异常等问题,确保显示设备完美点亮。

1a2s3d4f5g的博客 879

探索现代编程之道:C++11-14新特性深度解析

探索现代编程之道:C++11-14新特性深度解析 去发现同类优质开源项目:https://gitcode.com/ 随着C++语言的不断演进,C++11和C++14这两个里程碑式的版本为我们带来了前所未有的编程便捷性和效率提升。今天,我们重点推荐一个宝藏级开源项目——C++11-14新特性教程,它旨在引导您穿越这一变革之旅,解锁C++的现代编程技巧。 项目简介 此项目聚焦于一份详尽的PDF教程,标...

gitblog_06610的博客 394

前沿探索:基于强化学习的目标检测与跟踪技术及论文解析

前沿探索:基于强化学习的目标检测与跟踪技术及论文解析 ,人工智能,计算机视觉,大模型,AI,本文聚焦基于强化学习的目标检测与跟踪技术,先介绍相关技术基础,包括目标检测、跟踪及强化学习的算法等。接着阐述强化学习在目标检测与跟踪中的应用思路、框架及典型算法,解析三篇相关论文的背景、方法、实验结果。还探讨了该技术面临的样本效率、奖励函数设计等挑战,以及结合迁移学习等的未来发展方向,为该领域研究提供参考。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 11万+

YOLOv11改进策略【Backbone/主干网络】|替换HGNetV2骨干,包含RT-DETR中的l、x模型

本文记录的是基于HGNetv2的YOLOv11目标检测改进方法研究。本文利用HGNetv2替换YOLOv11的骨干网络,HGNetv2 通过其 GPU 推理友好的 3×3 标准卷积和层次化 HG Block 结构,能够为骨干网络提供高效且完整的特征提取能力。并且其中的和可在降低计算量的同时丰富特征表达,增强对多尺度目标特征的捕获能力,进而提高模型精度。本文配置了原论文中rtdetr-lrtdetr-x,以满足不同算力和检测精度的需求。

Limiiiing的博客 673

从入门到深入:C++语言的演进与现代开发价值解析

C++是一门“不简单”的语言,它融合了底层能力与高层抽象,是系统世界与应用世界的桥梁。尽管学习曲线较陡,但只要坚持实践,终将掌握它带来的巨大开发能量。在当今追求性能与可维护性并存的开发环境中,C++仍然值得每一位开发者投入时间去学习与深入。

2401_88419115的博客 1062

S7-1500——(一)西门子PLC编程从入门到精通4、SCL间接寻址

学习目标是在掌握博途平台SCL编程语言的基本使用基础之上,进一步了解SCL语言环境下的间接寻址过程,初步具备编写复杂控制程序的能力;在编写plc程序过程中, 需要对plc中的数据进行访问,这就是寻址;直接寻址间接寻址;直接寻址直接寻址就是直接对数据的存储单元进行访问;根据表达方式的不同,可分为绝对寻址和符号寻址;对于plc中的标准数据存储区包括IQMTCL以及标准数据块,既可以使用绝对寻址,也可以使用符号寻址;绝对寻址在使用绝对寻址时,可以寻址的宽度包括位,字,节字,双字;

大小曲奇的博客 2121

2024年博客成长记:成就、挑战与未来展望

引言 从阅读者成为创作者;成长:技术深度的拓展与分享;挑战:保持高质量输出与持续创新;未来展望:提升创作质量与拓展领域;结语

小林熬夜学习编程的博客 1984

RV1126 ROS2环境交叉编译及部署(基于官方Docker)

我的所有基于`RV1126`的机器人项目都是在`Ubuntu22.04`下进行开发的,在`Ubuntu18.04 Docker`容器中实现`RV1126`的`SDK`编译,详细可参考我之前的博客[《Ubuntu20.04/22.04下Docker方案实现多平台SDK编译》第2章](https://blog.youkuaiyun.com/w1820020635/article/details/147342689),`RV1126`的`ROS1`部署没什么难度,可以参考我之前的博客,这里记录了`ROS2`交叉编译及问题解决

w1820020635的博客 1143

视觉Transformer实战 | 将卷积引入视觉Transformer(CvT)

CvT 是一种融合卷积神经网络与 Vision Transformer 优势的视觉模型,旨在解决 ViT 缺乏平移不变性和局部性等归纳偏置的问题。CvT 采用分层结构逐级降采样,使用卷积词元嵌入代替传统 patch 切分,引入卷积投影替代线性投影。这些设计使得 CvT 能够去除位置编码,在高分辨率输入下表现更优。本节深入解析 CvT 的核心原理,并提供完整的 PyTorch 代码实现,演示如何在实际数据集上训练和评估 CvT 模型。

盼小辉丶的博客 726

《Java、Python与C++的协同进化跨平台开发的效率革命与未来趋势洞察》

更值得注意的是,NumPy团队开发的Numba扩展库,通过CUDA加速,将Python代码转换为GPU可直接运行的PTX汇编指令,相关案例在AWS EC2实例上实测性能提升达2000%。区块链领域的跨链技术方案,如Polkadot的XCMP(跨共识消息传递)协议,虽然展示出分布式系统安全性范式的潜力,但其复杂度增加了来自新兴领域的技术迁移成本。在软件技术日新月异的今天,Java、Python与C++作为三大主流编程语言,已形成稳固的技术生态壁垒,其互相补充的特性正在重塑跨平台开发的产业格局。

VEyUwZnQ的博客 913

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C++20新规大揭秘

在这个版本中,C++引入了诸多令人振奋的新特性,它们如同星星之火,在不同的应用场景下点亮了程序员的灵感之光。对了,各位看官,小生才情有限,笔墨之间难免会有不尽如人意之处,还望多多包涵,不吝赐教。通过将代码直接分割成独立的模块,不再需要头文件来声明接口,这不仅减少了重复编译的时间,还简化了依赖关系的管理。你可以把这里当作自己的家,无论是工作之余的小憩,还是寻找灵感的驿站,我都希望你能在这里找到属于你的那份快乐和满足。

master_chenchen的博客 931

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Dev C++ 的进化之旅:从经典 IDE 到现代编程教育的桥梁

本文探讨了Dev C++从经典IDE到现代编程教育桥梁的演进历程。详细介绍了其下载、安装和配置教程,分析了其在教育领域的独特价值,包括轻量级设计、标准化环境和现代C++支持,使其成为编程教学和竞赛的首选工具。

a1b2c3d的博客 790

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Dev C++ 初学者入门指南:从安装配置到高效编程调试

集成开发环境(IDE)是程序员编写、编译和调试代码的核心工具,其设计理念直接影响开发效率和学习曲线。对于C/C++初学者而言,理解编译器工作原理和项目管理是入门关键。Dev C++作为一个轻量级、开箱即用的IDE,通过集成GCC编译器,为新手提供了免配置的编程环境,极大降低了学习门槛。其价值在于让学习者能快速聚焦于语法和算法逻辑,而非复杂的环境搭建。在高校教学和个人练习场景中,这种简单直接的特性使其成为理想的起点工具。本文围绕Dev C++的安装、汉化、项目管理和调试等核心功能展开,特别针对编译错误排查和第

weixin_34187862的博客 468

推荐开源项目:安全的C++库——`sfc`

推荐开源项目:安全的C++库——sfc sfcrc is rust in c++项目地址:https://gitcode.com/gh_mirrors/sf/sfc 在这个程序开发日新月异的时代,我们常常追求更高效、更稳定的技术解决方案。今天,我想要向大家推荐一个名为sfc(safe c++)的开源项目,它旨在为开发者提供一种更加安全且高效的C++编程体验。 1. 项目介绍 sfc是一个针对C+...

gitblog_00099的博客 451

学习分享 | 适合初学者练习的C/C++开源项目

前言: 相信很多同学在初学C、C++时都会遇到这样一个问题,就是学习完书本上的各种概念后,对各个知识点有了一定的了解但又无法深入理解其原理。或者没有动手实际应用,对知识的掌握也只流于表面。一但自己上手实际开发,就无从下手。这就要求我们在学习过程中,既要了解理论知识,也得实操写代码,理解具体应用方法。但要实际开发做项目,估计很多同学也难以找到既能完成对C/C++框架梳理,又适合新手的开发项目。故本文向大家推荐一些寻找的渠道和一些优质的项目。 第一个要向大家推荐的是这个网站:https://www.hello.

AMOVLAB(阿木实验室) 6389
上一篇: C++日新月异的未来代码:C++11(上)
下一篇: C++内存列传之RAII宇宙:智能指针
澪贰
澪贰 优质创作者: C/C++技术领域 优质创作者: C/C++技术领域
博客等级 码龄2年 1万+粉丝 222原创
评论 62
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值