预习

#include <iostream>
#include <string>
#include <vector>

struct Test
{

};
struct Vertex
{
	float x, y, z;

	//有了其他的构造函数,如果需要用到无参构造函数,
	//就必须手动写一个
	Vertex()
	{

	}

	//因为有构造函数了,所以Vertex 结构体不是一个聚合类型(
	// 有构造函数),所以要使用显示构造函数
	// 使 Vertex v = { 1,2,3 }; 编译通过
	Vertex(float x, float y, float z)
	{
		this->x = x;
		this->y = y;
		this->z = z;
	}

	//参数必须是&,原因如下:
	//1. 当你尝试通过 Vertex a = b; 调用复制构造函数时,你需要将 b 传递给参数 other。
	//2. 在 C++ 中,按值传递(Pass by Value)参数本身就会触发一次复制。
	//3. 为了复制 b 到 other,编译器又需要调用复制构造函数。[死循环了]
	//因为main中使用 vector.push({1,2,3}) 需要将临时对象拷贝到vector中,所以这里的参数
	//必须是const
	Vertex(const Vertex& vertex)
	{
		std::cout << "copied constructor handled" << std::endl;
		this->x = vertex.x;
		this->y = vertex.y;
		this->z = vertex.z;
	}
	/*virtual*/ void test()
	{

	}

	~Vertex()
	{
		std::cout << "destructor handled" << std::endl;
	}
};

std::ostream& operator<<(std::ostream& stream, const Vertex& vertex)
{
	stream << vertex.x << "," << vertex.y << "," << vertex.z;
	return stream;
}

//使用引用避免复制整个数组
void Function(const std::vector<Vertex>& vertices)
{

}

int main()
{
	std::vector<Vertex> vertices;
	//vertices.push_back({ 1,2,3 });
	//std::cout << "==0===" << std::endl;
	//vertices.push_back({ 4,5,6 });

	//对上面两行代码优化
	// 1. 预先分配内存,防止搬家
	vertices.reserve(1);
	// 2. 原地构造,防止临时拷贝
	vertices.emplace_back(1, 2, 3);
	std::cout << "==0===" << std::endl;
	//超出容量,会拷贝原来的{1,2,3}到新数组,并且销毁
	// 原数组中的{1,2,3}
	vertices.emplace_back(4, 5, 6);


	std::cout << "==1===" << std::endl;
	Function(vertices);
	std::cout << "==2===" << std::endl;
	vertices.erase(vertices.begin() + 1);
	std::cout << "==3===" << std::endl;
	for (Vertex& v : vertices)
		std::cout << v << std::endl;
	std::cin.get();
}
/*
copied constructor handled //第一个临时对象复制到vector中之后,马上又销毁了
destructor handled
==0===
copied constructor handled //空间不够了,需要把第一个元素复制到新数组中。第二个元素创建临时对象,并复制到新数组中
copied constructor handled
destructor handled  //旧的数组中的第一个元素被销毁了
destructor handled  //第二个元素的临时对象被销毁了
==1===
==2===
destructor handled
==3===
1,2,3
*/

/*优化后不需要把临时对象复制到vector中,也不需要销毁临时对象了
==1===
==2===
destructor handled
==3===
1,2,3
*/

了解环境是优化过程中最重要的事情之一

  • 环境,即这个过程造成运行慢的原因、流程。当下,是对复制操作进行优化
#include <iostream>
#include <vector>

struct Vertex
{
	float x, y, z;
	Vertex(float x, float y, float z)
		:x(x), y(y), z(z)
	{


	}

	Vertex(const Vertex& vertex)
		:x(vertex.x), y(vertex.y), z(vertex.z)
	{
		std::cout << "Copied!" << x << y << z << std::endl;
	}
};

int main()
{
	//它的意图:它不是在“预留空间”,而是在创建对象。它告诉编译器:“请立刻为我创建 3 个 Vertex 对象,并把它们放进 vector 里。”
	//矛盾点:由于你没有给这 3 个对象提供初始值,编译器会尝试调用
	//vertex 的无参构造函数(Default Constructor)。
	//死胡同:在你的代码里,你定义了一个 Vertex(float x, float y, float z)。根据 C++ 规则,如果你定义了任何有参数的构造函数,编译器就不会再自动为你生成那个默认的空构造函数了。
	//std::vector<Vertex> vertices(3);

	std::vector<Vertex> vertices;
	////问题11: 这里先在主函数的栈帧中构造Vertex,然后再复制到vector中
	////问题22:vertices的大小默认为1 
	//vertices.push_back(Vertex(1, 2, 3));
	////为了再加一个元素,vertices的大小调整为2
	//vertices.push_back(Vertex(4, 5, 6));
	////为了再加一个元素,vertices的大小调整为3
	//vertices.push_back(Vertex(7, 8, 9));

	//优化
	//预留3个容量
	vertices.reserve(3);
	//直接在vector中构造vertice,而不是先在栈中
	//构造vertice再复制到vector中
	//告诉vector,在实际的vector内存中,用以下参数(1,2,3)构造
	//Vertex对象
	vertices.emplace_back(1, 2, 3);
	vertices.emplace_back(4, 5, 6);
	vertices.emplace_back(7, 8, 9); 

	std::cin.get();
}