优化std::vector的使用:避免不必要的拷贝

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

问题分析

让我们先看一个简单的三维向量类Vector3D的实现和使用std::vector<Vector3D>的示例:

代码示例

class Vector3D
{
private:
	int m_X, m_Y, m_Z;
public:
	Vector3D(int x, int y, int z)
		: m_X(x), m_Y(y), m_Z(z)
	{
		std::cout << "Vector3D(" << m_X << ',' << m_X << ',' << m_X << ") is created" << std::endl;
	}
	Vector3D(const Vector3D& vec)
		: m_X(vec.m_X), m_Y(vec.m_Y), m_Z(vec.m_Z)
	{
		std::cout << "Copied!!" << std::endl;
	}
	friend std::ostream& operator<<(std::ostream& stream, const Vector3D& vec);
};

std::ostream& operator<<(std::ostream& stream, const Vector3D& vec)
{
	stream << vec.m_X << ',' << vec.m_Y << ',' << vec.m_Z;
	return stream;
}

int main()
{
	std::vector<Vector3D> v;
	v.push_back(Vector3D(1, 2, 3));
	v.push_back(Vector3D(2, 3, 4));
	v.push_back(Vector3D(3, 4, 5));

	for (const Vector3D& it : v)
	{
		std::cout << it << std::endl;
	}
}

运行结果

Vector3D(1,1,1) is created
Copied!!
Vector3D(2,2,2) is created
Copied!!
Copied!!
Vector3D(3,3,3) is created
Copied!!
Copied!!
Copied!!
1,2,3
2,3,4
3,4,5

从输出可以看出存在两个主要问题:

  1. 临时对象拷贝:每次调用push_back时,都会先构造一个临时Vector3D对象,然后再将其拷贝到vector中
  2. 容量扩展拷贝:当vector容量不足时,会分配新的内存空间并将原有元素全部拷贝过去,导致额外的拷贝操作

解决方法

针对上述两个问题,我们在使用的过程中需要注意使用方式:

1. 预先分配足够容量

使用reserve()方法预先分配足够的空间,避免动态扩容带来的拷贝开销:

std::vector<Vector3D> v;
v.reserve(3);  // 预先分配3个元素的空间

2. 使用emplace_back替代push_back

emplace_back直接在vector的内存空间中构造对象,避免了临时对象的创建和拷贝:

v.emplace_back(1, 2, 3);  // 直接在vector中构造对象

优化后的代码示例

class Vector3D
{
private:
	int m_X, m_Y, m_Z;
public:
	Vector3D(int x, int y, int z)
		: m_X(x), m_Y(y), m_Z(z)
	{
		std::cout << "Vector3D(" << m_X << ',' << m_X << ',' << m_X << ") is created" << std::endl;
	}
	Vector3D(const Vector3D& vec)
		: m_X(vec.m_X), m_Y(vec.m_Y), m_Z(vec.m_Z)
	{
		std::cout << "Copied!!" << std::endl;
	}
	friend std::ostream& operator<<(std::ostream& stream, const Vector3D& vec);
};

std::ostream& operator<<(std::ostream& stream, const Vector3D& vec)
{
	stream << vec.m_X << ',' << vec.m_Y << ',' << vec.m_Z;
	return stream;
}

int main()
{
	std::vector<Vector3D> v;
	v.reserve(3);
	v.emplace_back(1, 2, 3);
	v.emplace_back(2, 3, 4);
	v.emplace_back(3, 4, 5);

	for (const Vector3D& it : v)
	{
		std::cout << it << std::endl;
	}
}

运行结果

Vector3D(1,1,1) is created
Vector3D(2,2,2) is created
Vector3D(3,3,3) is created
1,2,3
2,3,4
3,4,5

可以看到,优化后的代码完全消除了不必要的拷贝操作,效率显著提高。

总结

通过合理使用reserveemplace_back,我们可以显著减少std::vector使用过程中的不必要拷贝,提高程序性能。这种优化对于包含复杂对象的vector尤为重要。记住:预先规划好容量,尽量直接在容器中构造对象,是高效使用std::vector的关键。

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MBHB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值