学习了移动构造,不太清楚它到底什么时候使用,感觉他是把原来的指针置空,然后重新分配一个指针指向这块内存。既然是和指针有关系,那是不是只能在堆区分配空间的时候才能用到?
说白了移动构造函数就是可以避免不必要的复制操作,提高程序的效率。不只限于堆区,像使用容器操作,创建临时对象时都可以避免不必要的复制操作
//定位到txt文件的某一行
ifstream & seek_to_line(ifstream & in, int line)
//将打开的文件in,定位到line行。
{
int i;
char buf[1024];
in.seekg(0, ios::beg); //定位到文件开始。
for (i = 0; i < line; i++)
{
in.getline(buf, sizeof(buf));//读取行。
}
return in;
}
int _tmain(int argc, _TCHAR* argv[])
{
//读取文件路径
std::string pts_filename = "E:/数据文件/20190718.txt";
std::vector<Point3D> pts;
{
std::ifstream pts_file;
pts_file.open(pts_filename);
seek_to_line(pts_file, 2); //定位到指定的行开始读取
if (!pts_file.is_open())
{
cout << "Unable to open myfile";
system("pause");
exit(1);
}
while (!pts_file.eof())
{
//先忽略前面的2列,从第三列开始读取,读取了3-5列x,y,z的数据保存到point3D中,然后
//当前行后面的数据全部忽略
for (Point3D pt; (((pts_file >> ws).ignore(numeric_limits<streamsize>::max(), ' ') >> ws).ignore(numeric_limits<streamsize>::max(), ' ') >> pt.x >> pt.y >> pt.z >> ws).ignore(numeric_limits<streamsize>::max(), '\n');)
{
pts.push_back(pt); //将数据保存下来
}
}
pts_file.close();
}
return 0;
}
由于后来需要用到一些windows的函数,出现了编译错误,参考了链接:https://blog.csdn.net/huixingshao/article/details/86534865。std::numeric_limits::max()使用的是STL中的z数值极限<Numeric Limits>,如果又添加了#include<windows.h>则会出现如下错误:
warning C4003: “max”宏的实参不足
error C2589: “(” : “::”右边的非法标记
因为需要把max用括号括起来避免和windows定义的宏混淆
(std::numeric_limits<double>::max)()
因为Windef.h中定义了
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
所以会产生编译错误。
移动构造函数是C++11引入的一种特殊类型的构造函数,用于将右值引用的对象的资源(比如堆空间、文件句柄等)转移给另一个对象,而不是发生一次深拷贝。移动构造函数通常用于提高程序的性能和效率,尤其在处理大规模的数据时更为明显。
当一个类重载了移动构造函数时,如果类的对象要被移动而不是被拷贝,就会调用移动构造函数。移动构造函数的形式为“类名(类名&&)”。其中“&&”表示右值引用。
下面给出一个简单的例子,展示了如何在类中重载移动构造函数:
#include <iostream>
#include <string>
#include <utility>
class MyClass {
public:
// 普通构造函数
MyClass(std::string s) : str_(std::move(s)) {
std::cout << "Constructing MyClass with string: " << str_ << std::endl;
}
// 移动构造函数
MyClass(MyClass&& other) : str_(std::move(other.str_)) {
std::cout << "Moving contents from MyClass with string: " << str_ << std::endl;
}
private:
std::string str_;
};
int main() {
MyClass a("Hello, world!"); // 普通构造函数
MyClass b(std::move(a)); // 使用 std::move 移动 a 中的数据到 b 中
return 0;
}
在这个例子中,我们定义了一个 MyClass
类,含有一个普通构造函数和一个移动构造函数。在主函数中,我们首先使用普通构造函数创建了一个 MyClass 对象 a。然后,我们使用 std::move 将 a 中的资源(即字符串 "Hello, world!")移动到 b 对象中,这里将会调用移动构造函数。
需要注意的是,移动构造函数并不会释放被移动对象的资源,被移动对象还是需要进行析构,只不过其资源已经转移给了新创建的对象。所以,在移动构造函数中,我们通常需要将被移动对象的指针或者引用设置为空,避免被移动对象和移动后的对象同时拥有相同的资源。
移动构造函数往往可以应用于对象的智能指针和容器(比如 vector)等场景中,可以大大提高程序的效率。