局部路径规划算法 - 贝塞尔曲线法 C++ matlab

2024-03-19 17:12

本文主要是介绍局部路径规划算法 - 贝塞尔曲线法 C++ matlab,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考资料:
(1)贝塞尔曲线法
(2)曲线杂谈(二):Bezier曲线的特殊性质

贝塞尔曲线法

1 算法概述

1.1 算法简介
  • 贝塞尔曲线于1962年由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线(可视化)来为汽车的主体进行设计。
  • 贝塞尔曲线是应用于二维图形应用程序的数学曲线,由一组称为控制点的向量来确定,给定的控制点按顺序连接构成控制多边形,贝塞尔曲线逼近这个多边形,进而通过调整控制点坐标改变曲线的形状。
1.2 算法思想

对于车辆系统,规划的轨迹应满足以下准则:
① 轨迹连续
② 轨迹曲率连续
③ 轨迹容易被车辆跟随
④ 容易生成

给定 n + 1 n+1 n+1个数据点, p 0 − p n p_0-p_n p0pn,生成一条曲线,使得该曲线与这些点描述的形状相符。
在这里插入图片描述

2 算法原理

2.1 一阶贝塞尔曲线

一阶贝塞尔曲线需要2个控制点,假设分别为 P 0 P_0 P0 P 1 P_1 P1。则贝塞尔曲线上的生成点 p 1 ( t ) p_1(t) p1(t)可以表达为:
p 1 ( t ) = P 0 + ( P 1 − P 0 ) t → p 1 ( t ) = ( 1 − t ) P 0 + t P 1 t ∈ [ 0 , 1 ] p_{1}(t)=P_{0}+\left(P_{1}-P_{0}\right) t \rightarrow p_{1}(t)=(1-t) P_{0}+t P_{1} \\ t∈[0,1] p1(t)=P0+(P1P0)tp1(t)=(1t)P0+tP1t[0,1]
一阶曲线就是根据t来的线性插值。
在这里插入图片描述

2.2 二阶贝塞尔曲线

二阶贝塞尔曲线需要3个控制点,假设分别为 P 0 P_0 P0 P 1 P_1 P1 P 2 P_2 P2 P 0 P_0 P0 P 1 P_1 P1构成一阶, P 1 P_1 P1 P 2 P_2 P2构成一阶:
{ p 1 , 1 ( t ) = ( 1 − t ) P 0 + t P 1 p 1 , 2 ( t ) = ( 1 − t ) P 1 + t P 2 \left\{\begin{array}{l} p_{1,1}(t)=(1-t) P_{0}+t P_{1} \\ p_{1,2}(t)=(1-t) P_{1}+t P_{2} \end{array}\right. {p1,1(t)=(1t)P0+tP1p1,2(t)=(1t)P1+tP2
在生成的两个一阶点基础上,可以生成二阶贝塞尔点:
p 2 ( t ) = ( 1 − t ) p 1 , 1 + t p 1 , 2 p_{2}(t)=(1-t) p_{1,1}+t p_{1,2} p2(t)=(1t)p1,1+tp1,2
则贝塞尔点与3个控制点的关系为:
p 2 ( t ) = ( 1 − t ) 2 P 0 + 2 t ( 1 − t ) P 1 + t 2 P 2 t ∈ [ 0 , 1 ] p_{2}(t)=(1-t)^{2} P_{0}+2 t(1-t) P_{1}+t^{2} P_{2} \\ t∈[0,1] p2(t)=(1t)2P0+2t(1t)P1+t2P2t[0,1]
在这里插入图片描述

2.3 三阶贝塞尔曲线

三阶贝塞尔曲线有4个控制点,假设分别为 P 0 P_0 P0, P 1 P_1 P1, P 2 P_2 P2, P 3 P_3 P3 P 0 P_0 P0 P 1 P_1 P1 P 1 P_1 P1 P 2 P_2 P2 P 2 P_2 P2 P 3 P_3 P3都构成一阶:
{ p 1 , 1 ( t ) = ( 1 − t ) P 0 + t P 1 p 1 , 2 ( t ) = ( 1 − t ) P 1 + t P 2 p 1 , 3 ( t ) = ( 1 − t ) P 2 + t P 3 \left\{\begin{array}{l} p_{1,1}(t)=(1-t) P_{0}+t P_{1} \\ p_{1,2}(t)=(1-t) P_{1}+t P_{2} \\ p_{1,3}(t)=(1-t) P_{2}+t P_{3} \end{array}\right. p1,1(t)=(1t)P0+tP1p1,2(t)=(1t)P1+tP2p1,3(t)=(1t)P2+tP3
在生成的三个一阶点基础上,可以生成两个二阶贝塞尔点:
{ p 2 , 1 ( t ) = ( 1 − t ) p 1 , 1 + t p 1 , 2 p 2 , 2 ( t ) = ( 1 − t ) p 1 , 2 + t p 1 , 3 \left\{\begin{array}{l} p_{2,1}(t)=(1-t) p_{1,1}+t p_{1,2} \\ p_{2,2}(t)=(1-t) p_{1,2}+t p_{1,3} \end{array}\right. {p2,1(t)=(1t)p1,1+tp1,2p2,2(t)=(1t)p1,2+tp1,3
在生成的两个二阶点基础上,可以生成三阶贝塞尔点:
p 3 ( t ) = ( 1 − t ) p 2 , 1 + t p 2 , 2 p_{3}(t)=(1-t) p_{2,1}+t p_{2,2} p3(t)=(1t)p2,1+tp2,2
即:
p 3 ( t ) = ( 1 − t ) 3 P 0 + 3 t ( 1 − t ) 2 P 1 + 3 t 2 ( 1 − t ) P 2 + t 3 P 3 p_{3}(t)=(1-t)^{3} P_{0}+3 t(1-t)^{2} P_{1}+3 t^{2}(1-t) P_{2}+t^{3} P_{3} p3(t)=(1t)3P0+3t(1t)2P1+3t2(1t)P2+t3P3
在这里插入图片描述

2.4 n阶贝塞尔曲线

对于 P 0 , P 1 , P 2 , … , P n P_{0}, P_{1}, P_{2}, \ldots, P_{n} P0,P1,P2,,Pn n + 1 n+1 n+1个控制点而言,贝塞尔点定义为:
p n ( t ) = ∑ i = 0 n C n i ⋅ ( 1 − t ) n − i ⋅ t i ⋅ P i = ∑ i = 0 n B i , n ( t ) ⋅ P i p_{n}(t)=\sum_{i=0}^{n} C_{n}^{i} \cdot(1-t)^{n-i} \cdot t^{i} \cdot P_{i}=\sum_{i=0}^{n} B_{i, n}(t) \cdot P_{i} pn(t)=i=0nCni(1t)nitiPi=i=0nBi,n(t)Pi
其中, B i , n ( t ) = C n i ⋅ ( 1 − t ) n − i ⋅ t i B_{i, n}(t)=C_{n}^{i} \cdot(1-t)^{n-i} \cdot t^{i} Bi,n(t)=Cni(1t)niti称为伯恩斯坦基函数。伯恩斯坦基函数的一阶导数为:
B i , n ′ ( t ) = [ C n i ⋅ ( 1 − t ) n − i ⋅ t i ] ′ = n ! i ! ⋅ ( n − i ) ! ⋅ [ − ( n − i ) ⋅ ( 1 − t ) n − i − 1 ⋅ t i + i ⋅ t i − 1 ⋅ ( 1 − t ) n − i ] = n ! i ! ⋅ ( n − i ) ! ⋅ i ⋅ t i − 1 ⋅ ( 1 − t ) n − i − n ! i ! ⋅ ( n − i ) ! ⋅ ( n − i ) ⋅ ( 1 − t ) n − i − 1 ⋅ t i = n ( n − 1 ) ! ( i − 1 ) ! ⋅ ( n − i ) ! t i − 1 ⋅ ( 1 − t ) n − i − n ( n − 1 ) ! i ! ⋅ ( n − i − 1 ) ! ⋅ ( 1 − t ) n − i − 1 ⋅ t i = n C n − 1 i − 1 t i − 1 ⋅ ( 1 − t ) n − i − n C n − 1 i ( 1 − t ) n − i − 1 ⋅ t i = n [ B i − 1 , n − 1 ( t ) − B i , n − 1 ( t ) ] \begin{array}{l} B_{i, n}^{\prime}(t)=\left[C_{n}^{i} \cdot(1-t)^{n-i} \cdot t^{i}\right]^{\prime} \\ =\frac{n !}{i ! \cdot(n-i) !} \cdot\left[-(n-i) \cdot(1-t)^{n-i-1} \cdot t^{i}+i \cdot t^{i-1} \cdot(1-t)^{n-i}\right] \\ =\frac{n !}{i ! \cdot(n-i) !} \cdot i \cdot t^{i-1} \cdot(1-t)^{n-i}-\frac{n !}{i ! \cdot(n-i) !} \cdot(n-i) \cdot(1-t)^{n-i-1} \cdot t^{i} \\ =n \frac{(n-1) !}{(i-1) ! \cdot(n-i) !} t^{i-1} \cdot(1-t)^{n-i}-n \frac{(n-1) !}{i ! \cdot(n-i-1) !} \cdot(1-t)^{n-i-1} \cdot t^{i} \\ =n C_{n-1}^{i-1} t^{i-1} \cdot(1-t)^{n-i}-n C_{n-1}^{i}(1-t)^{n-i-1} \cdot t^{i}=n\left[B_{i-1, n-1}(t)-B_{i, n-1}(t)\right] \end{array} Bi,n(t)=[Cni(1t)niti]=i!(ni)!n![(ni)(1t)ni1ti+iti1(1t)ni]=i!(ni)!n!iti1(1t)nii!(ni)!n!(ni)(1t)ni1ti=n(i1)!(ni)!(n1)!ti1(1t)nini!(ni1)!(n1)!(1t)ni1ti=nCn1i1ti1(1t)ninCn1i(1t)ni1ti=n[Bi1,n1(t)Bi,n1(t)]
其中, i ≥ 1 i≥1 i1。当 i = 0 i=0 i=0 B 0 , n ( t ) = C n 0 ⋅ ( 1 − t ) n − 0 ⋅ t 0 = ( 1 − t ) n B_{0, n}(t)=C_{n}^{0} \cdot(1-t)^{n-0} \cdot t^{0}=(1-t)^{n} B0,n(t)=Cn0(1t)n0t0=(1t)n,故 B 0 , n ′ ( t ) = − n ( 1 − t ) n − 1 = − n B 0 , n − 1 B_{0, n}^{\prime}(t)=-n(1-t)^{n-1}=-nB_{0, n-1} B0,n(t)=n(1t)n1=nB0,n1
则贝塞尔点求导:
p n ′ ( t ) = [ ∑ i = 0 n C n i ⋅ ( 1 − t ) n − i ⋅ t i ⋅ P i ] ′ = B 0 , n ′ P 0 + B 1 , n ′ P 1 + ⋯ + B n , n ′ ⋅ P n = 0 + n ( B 0 , n − 1 − B 1 , n − 1 ) P 1 + n ( B 1 , n − 1 − B 2 , n − 1 ) P 2 ⋯ + n ( B n − 1 , n − 1 − B n , n − 1 ) P n = n [ B 0 , n − 1 ( P 1 − P 0 ) + B 1 , n − 1 ( P 2 − P 1 ) + ⋯ + B n − 1 , n − 1 ( P n − P n − 1 ) ] = n ∑ i = 1 n B i − 1 , n − 1 ( t ) ⋅ ( P i − P i − 1 ) \begin{array}{l} p_{n}^{\prime}(t)=\left[\sum_{i=0}^{n} C_{n}^{i} \cdot(1-t)^{n-i} \cdot t^{i} \cdot P_{i}\right]' \\ =B_{0, n}^{\prime} P_{0}+B_{1, n}^{\prime} P_{1}+\cdots+B_{n, n}^{\prime} \cdot P_{n} \\ =0+n\left(B_{0, n-1}-B_{1, n-1}\right) P_{1}+n\left(B_{1, n-1}-B_{2, n-1}\right) P_{2} \cdots+n\left(B_{n-1, n-1}-B_{n, n-1}\right) P_{n} \\ =n\left[B_{0, n-1}\left(P_{1}-P_{0}\right)+B_{1, n-1}\left(P_{2}-P_{1}\right)+\cdots+B_{n-1, n-1}\left(P_{n}-P_{n-1}\right)\right] \\ =n \sum_{i=1}^{n} B_{i-1, n-1}(t) \cdot\left(P_{i}-P_{i-1}\right) \end{array} pn(t)=[i=0nCni(1t)nitiPi]=B0,nP0+B1,nP1++Bn,nPn=0+n(B0,n1B1,n1)P1+n(B1,n1B2,n1)P2+n(Bn1,n1Bn,n1)Pn=n[B0,n1(P1P0)+B1,n1(P2P1)++Bn1,n1(PnPn1)]=ni=1nBi1,n1(t)(PiPi1)

3 贝塞尔曲线性质

参考知乎大佬:曲线杂谈(二):Bezier曲线的特殊性质这篇文章
① 各项系数之和为1
② 系数对称性
③ 曲线的起始点和终点对应第一个和最后一个控制点
④ 凸包性

贝塞尔曲线被包含了所有控制点的最小凸多边形所包含, 这里要和控制点依次围成的最小多边形区分开。

可以通过控制点的凸包来限制规划曲线的范围
在这里插入图片描述从图上可以看到,按照控制点顺序(A->B->C->D…)连接的多边形有一部分是“凹陷”的(蓝色多段线)。黄色的凸包将所有控制点(及它们之间的连线)以及贝塞尔曲线包含在内。
⑤ 一阶导数
贝塞尔曲线起始点和第一个控制点相切,终止点和最后一个控制点相切。可根据曲线的起始点和终止点的切线方向确定车辆起始点姿态和目标点姿态
在这里插入图片描述
⑥ 几何不变性

指某些几何特性不随坐标变换而变化的特性,Bezier曲线的形状仅与控制多边形各顶点的相对位置有关,而与坐标系的选择无关。

⑦ 波折递减性:控制折线比它定义的曲线复杂
⑧ 贝塞尔曲线的拼接:首尾控制点相接;连接处的四个控制点共线

若要求两端弧线拼接在一起依然是曲率连续的,必须要求两段弧线在连接处的曲率是相等的

至少需要三阶贝塞尔曲线(四个控制点)才能生成曲率连续的路径
k = ∣ f ′ ′ ( 1 + f ′ 2 ) 3 2 ∣ k=\left|\frac{f^{\prime \prime}}{\left(1+f^{\prime 2}\right)^{\frac{3}{2}}}\right| k= (1+f′2)23f′′

若要求曲率连续变化,则要求至少二阶导数连续,三阶贝塞尔曲线求两次导还有变量t,是关于t连续的

(1)城市环境下局部路径规划,如贝塞尔曲线能够拟合直道和弯道,在曲率变化较大的地方可以选用两个贝塞尔曲线来拟合
(2)无人驾驶车辆的运动规划,目标轨迹曲率是连续的且轨迹的曲率不超过车辆可行驶轨迹曲率的限制

4 代码实现

MATLAB(Ally)
main1.m

clc
clear
close all%% 直观动图感受贝塞尔曲线行程过程% 一次贝塞尔曲线
P0 = [0, 0];
P1 = [1, 1];
P = [P0; P1];
figure;
plot(P(:,1), P(:,2), 'k');
MakeGif('一次贝塞尔曲线.gif',1);
hold on
for t = 0:0.01:1P_t = (1-t)*P0 + t*P1;scatter(P_t(1), P_t(2), 200, '.r');stringName = "一次贝塞尔曲线:t =" + num2str(t);title(stringName)MakeGif('一次贝塞尔曲线.gif',t*100+1);
end% 二次贝塞尔曲线
P0 = [0, 0];
P1 = [1, 1];
P2 = [2, 1];
P = [P0; P1; P2];
figure;
plot(P(:,1), P(:,2), 'k');
MakeGif('二次贝塞尔曲线.gif',1);
hold on
scatter(P(:,1), P(:,2), 200, '.b');
for t = 0:0.01:1P_t_1 = (1-t)*P0 + t*P1;P_t_2 = (1-t)*P1 + t*P2;P_t_3 = (1-t)*P_t_1 + t*P_t_2;h1 = scatter(P_t_1(1), P_t_1(2), 300, '.g');h2 = scatter(P_t_2(1), P_t_2(2), 300, '.g');h3 = plot([P_t_1(1), P_t_2(1)], [P_t_1(2), P_t_2(2)], 'g', 'linewidth',2);    scatter(P_t_3(1), P_t_3(2), 300, '.r');stringName = "二次贝塞尔曲线:t =" + num2str(t);title(stringName)MakeGif('二次贝塞尔曲线.gif',t*100+1);delete(h1);delete(h2);delete(h3);
end% 三次贝塞尔曲线
P0 = [0, 0];
P1 = [1, 1];
P2 = [2, 1];
P3 = [3, 0];
P = [P0; P1; P2; P3];
figure;
plot(P(:,1), P(:,2), 'k');
MakeGif('三次贝塞尔曲线.gif',1);
hold on
scatter(P(:,1), P(:,2), 200, '.b');
for t = 0:0.01:1P_t_1_1 = (1-t)*P0 + t*P1;P_t_1_2 = (1-t)*P1 + t*P2;P_t_1_3 = (1-t)*P2 + t*P3;P_t_2_1 = (1-t)*P_t_1_1 + t*P_t_1_2;P_t_2_2 = (1-t)*P_t_1_2 + t*P_t_1_3;P_t_3 = (1-t)*P_t_2_1 + t*P_t_2_2;h1 = scatter(P_t_1_1(1), P_t_1_1(2), 300, '.b');h2 = scatter(P_t_1_2(1), P_t_1_2(2), 300, '.b');h3 = scatter(P_t_1_3(1), P_t_1_3(2), 300, '.b');h4 = plot([P_t_1_1(1); P_t_1_2(1)], [P_t_1_1(2); P_t_1_2(2)],  'b', 'linewidth',2);h5 = plot([P_t_1_2(1); P_t_1_3(1)], [P_t_1_2(2); P_t_1_3(2)],  'b', 'linewidth',2);h6 = scatter(P_t_2_1(1), P_t_2_1(2), 300, '.g');h7 = scatter(P_t_2_2(1), P_t_2_2(2), 300, '.g');h8 = plot([P_t_2_1(1); P_t_2_2(1)], [P_t_2_1(2); P_t_2_2(2)],  'g', 'linewidth',2);scatter(P_t_3(1), P_t_3(2), 300, '.r');stringName = "三次贝塞尔曲线:t =" + num2str(t);title(stringName)MakeGif('三次贝塞尔曲线.gif',t*100+1);delete(h1);delete(h2);delete(h3);delete(h4);delete(h5);delete(h6);delete(h7);delete(h8);end

main2.m

clc
clear
close all%% 
% 定义控制点
d = 3.5;
P0 = [0, -d/2];
P1 = [25, -d/2];
P2 = [25, d/2];
P3 = [50, d/2];
P = [P0; P1; P2; P3];% 直接根据贝塞尔曲线定义式得到路径点
n = length(P)-1;
Path = [];
for t = 0:0.01:1if n == 1p_t = P;elseif n >= 2p_t = [0, 0];for i = 0:nk_C = factorial(n) / (factorial(i) * factorial(n-i));k_t = (1-t)^(n-i) * t^i;p_t = p_t + k_C * k_t * P(i+1,:);endPath(end+1,:) = p_t;elsedisp('控制点输入有误,请重新输入')end
end%% 画图
d = 3.5;               % 道路标准宽度
W = 1.8;               % 汽车宽度
L = 4.7;               % 车长
figure
len_line = 50;% 画灰色路面图
GreyZone = [-5,-d-0.5; -5,d+0.5; len_line,d+0.5; len_line,-d-0.5];
fill(GreyZone(:,1),GreyZone(:,2),[0.5 0.5 0.5]);
hold on
fill([P0(1),P0(1),P0(1)-L,P0(1)-L],[-d/2-W/2,-d/2+W/2,-d/2+W/2,-d/2-W/2],'b')  % 画分界线
plot([-5, len_line],[0, 0], 'w--', 'linewidth',2);  %分界线
plot([-5,len_line],[d,d],'w','linewidth',2);     %左边界线
plot([-5,len_line],[-d,-d],'w','linewidth',2);  %左边界线% 设置坐标轴显示范围
axis equal
set(gca, 'XLim',[-5 len_line]); 
set(gca, 'YLim',[-4 4]); % 绘制路径
scatter(P(:,1),P(:,2),'g')
plot(P(:,1),P(:,2),'r');%路径点
scatter(Path(:,1),Path(:,2),200, '.b');%路径点

MakeGif.m

function MakeGif(filename,index)  f = getframe(gcf);  imind = frame2im(f);  [imind,cm] = rgb2ind(imind,256);  if index==1  imwrite(imind,cm,filename,'gif', 'Loopcount',inf,'DelayTime',0.001);else  imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',0.001);end  
end  

C++:
BezierCurve.h

#pragma once#include <iostream>
#include <Eigen/Dense>
#include <vector>
#include <cmath>
#include <algorithm>using namespace std;
using namespace Eigen;double factorial(int n);Vector2d bezierCommon(vector<Vector2d>& Ps, double t);

BezierCurve.cpp

#include "BezierCurve.h"// 阶乘实现
double factorial(int n) {if (n <= 1) return 1;return factorial(n - 1) * n;
}// 贝塞尔
Vector2d bezierCommon(vector<Vector2d>& Ps, double t) {if(Ps.size() == 1) return Ps[0];Vector2d p_t(0, 0);int n = Ps.size()-1;for(int i = 0; i < Ps.size(); i++){double C_n_i = factorial(n) / (factorial(i) * factorial(n-i));p_t +=  C_n_i * pow((1-t),(n-i)) * pow(t,i) * Ps[i];}return p_t;
}

main.cpp

#include "BezierCurve.h"
#include "matplotlibcpp.h"
namespace plt = matplotlibcpp;int main(int argc, char** argv) {// 四阶贝塞尔vector<Vector2d> Ps{Vector2d(0,0), Vector2d(1,1), Vector2d(2,1), Vector2d(3,0), Vector2d(4,2)};/*// 三阶vector<Vector2d> Ps{Vector2d(0,0), Vector2d(1,1), Vector2d(2,1), Vector2d(3,0)};// 二阶vector<Vector2d> Ps{Vector2d(0,0), Vector2d(1,1), Vector2d(2,1)};// 一阶vector<Vector2d> Ps{Vector2d(0,0), Vector2d(1,1)};*/vector<double> x_ref, y_ref;for(int i = 0; i < Ps.size(); i++){x_ref.push_back(Ps[i][0]);y_ref.push_back(Ps[i][1]);}vector<double> x_, y_;for (int t = 0; t < 100; t++) {plt::clf();Vector2d pos = bezierCommon(Ps, (double)t/100);x_.push_back(pos[0]);y_.push_back(pos[1]);plt::plot(x_, y_, "r");plt::plot(x_ref, y_ref);plt::pause(0.01);}// save figureconst char* filename = "./bezier_demo.png";plt::save(filename);plt::show();return 0;
}

运行结果:
四阶贝塞尔
在这里插入图片描述三阶贝塞尔
在这里插入图片描述二阶贝塞尔
在这里插入图片描述一阶贝塞尔
在这里插入图片描述


贝塞尔讲解正式结束,不正之处望读者指出

这篇关于局部路径规划算法 - 贝塞尔曲线法 C++ matlab的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/826706

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

C++的模板(八):子系统

平常所见的大部分模板代码,模板所传的参数类型,到了模板里面,或实例化为对象,或嵌入模板内部结构中,或在模板内又派生了子类。不管怎样,最终他们在模板内,直接或间接,都实例化成对象了。 但这不是唯一的用法。试想一下。如果在模板内限制调用参数类型的构造函数会发生什么?参数类的对象在模板内无法构造。他们只能从模板的成员函数传入。模板不保存这些对象或者只保存他们的指针。因为构造函数被分离,这些指针在模板外

随想录 Day 69 并查集 107. 寻找存在的路径

随想录 Day 69 并查集 107. 寻找存在的路径 理论基础 int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好vector<int> father = vector<int> (n, 0); // C++里的一种数组结构// 并查集初始化void init() {for (int i = 0; i < n; ++i) {father[i] = i;}

C++工程编译链接错误汇总VisualStudio

目录 一些小的知识点 make工具 可以使用windows下的事件查看器崩溃的地方 dumpbin工具查看dll是32位还是64位的 _MSC_VER .cc 和.cpp 【VC++目录中的包含目录】 vs 【C/C++常规中的附加包含目录】——头文件所在目录如何怎么添加,添加了以后搜索头文件就会到这些个路径下搜索了 include<> 和 include"" WinMain 和

C/C++的编译和链接过程

目录 从源文件生成可执行文件(书中第2章) 1.Preprocessing预处理——预处理器cpp 2.Compilation编译——编译器cll ps:vs中优化选项设置 3.Assembly汇编——汇编器as ps:vs中汇编输出文件设置 4.Linking链接——链接器ld 符号 模块,库 链接过程——链接器 链接过程 1.简单链接的例子 2.链接过程 3.地址和

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C++学习 贝蒂的主页:Betty’s blog 1. 泛型编程 首先让我们来思考一个问题,如何实现一个交换函数? void swap(int& x, int& y){int tmp = x;x = y;y = tmp;} 相信大家很快就能写出上面这段代码,但是如果要求这个交换函数支持字符型

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

C++入门01

1、.h和.cpp 源文件 (.cpp)源文件是C++程序的实际实现代码文件,其中包含了具体的函数和类的定义、实现以及其他相关的代码。主要特点如下:实现代码: 源文件中包含了函数、类的具体实现代码,用于实现程序的功能。编译单元: 源文件通常是一个编译单元,即单独编译的基本单位。每个源文件都会经过编译器的处理,生成对应的目标文件。包含头文件: 源文件可以通过#include指令引入头文件,以使