C++;如果不存在原始指针变量,则移动构造函数与复制构造函数 学习C++和所有关于构造函数(复制,移动)的东西,我想知道正确的/聪明的/有效的方法是什么。 以下场景: 我有一个班级电影,包含标题,评级和计数器。每次实例化该类的对象时,我都希望将该对象放入对象数组(称为Movies)中。因此,如果我看了3部电影,我的数组将包含类电影的三个实例。因为我的电影类不包含原始指针,所以我想知道使用copy或move将特定电影添加到我的收藏中是否会有性能上的差异。我希望我的想法是清楚的,以便更好地理解以下代码。希望有人能启发我。谢谢,
Mingw-w64版本8.1.0,Win10,VSCode:C++;如果不存在原始指针变量,则移动构造函数与复制构造函数 学习C++和所有关于构造函数(复制,移动)的东西,我想知道正确的/聪明的/有效的方法是什么。 以下场景: 我有一个班级电影,包含标题,评级和计数器。每次实例化该类的对象时,我都希望将该对象放入对象数组(称为Movies)中。因此,如果我看了3部电影,我的数组将包含类电影的三个实例。因为我的电影类不包含原始指针,所以我想知道使用copy或move将特定电影添加到我的收藏中是否会有性能上的差异。我希望我的想法是清楚的,以便更好地理解以下代码。希望有人能启发我。谢谢,,c++,C++,Mingw-w64版本8.1.0,Win10,VSCode: #include <iostream> #include <vector> using std::cout; using std::endl; using std::string; using std::vector; class Movie { private: string movieName; int movieRating; int movieCounter;
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
class Movie
{
private:
string movieName;
int movieRating;
int movieCounter;
public:
string getName();
Movie(string movieNameVal="None", int movieRatingVal=0);
Movie(const Movie &source);
Movie(Movie &&source);
~Movie();
};
Movie::Movie(string movieNameVal, int movieRatingVal)
: movieName(movieNameVal), movieRating(movieRatingVal) // Equivalent to movieName = movieNameVal; movieRating = movieRatingVal;
{
cout << "Constructor called" << endl;
}
// Copy constructor
Movie::Movie(const Movie &source)
: Movie(source.movieName, source.movieRating)
{
cout << "Copy constructor called" << endl;
}
// Move constructor
Movie::Movie(Movie &&source)
: movieName(source.movieName), movieRating(source.movieRating)
{
cout << "Move constructor called" << endl;
}
Movie::~Movie()
{
cout << "Destructor called" << endl;
}
int main()
{
{
vector<Movie> Movies1;
cout << "------------Movies1: Copy constructor version------------" << endl;
Movie movie1("Terminator 1", 5);
Movies1.push_back(movie1);
}
cout << endl;
cout << endl;
cout << endl;
{
vector<Movie> Movies2;
string namex = "Terminator 2";
int ratingx = 5;
cout << "------------Movies2: Move constructor version------------" << endl;
Movies2.push_back(Movie(namex, ratingx));
}
return 0;
}
#包括
#包括
使用std::cout;
使用std::endl;
使用std::string;
使用std::vector;
班级电影
{
私人:
字符串movieName;
国际电影;
国际电影计数器;
公众:
字符串getName();
电影(字符串movieNameVal=“无”,int movieRatingVal=0);
电影(康斯特电影和资料来源);
电影(电影和来源);
~Movie();
};
电影::电影(字符串movieNameVal,int movieRatingVal)
:movieName(movieNameVal),movieRating(movieRatingVal)//相当于movieName=movieNameVal;movieRating=movieRatingVal;
{
当您通过复制或移动特定类的对象实例来追加向量时,您可能会询问性能上的差异。
首先,您可以随时进行测量!我认为向量重新分配其容量()
所花费的大部分时间,因此,当您知道将插入的对象数量时,始终建议保留一些内存()
查看您的代码片段的输出:
------------Movies1: Copy constructor version------------
Constructor called
Constructor called
Copy constructor called
Destructor called
Destructor called
------------Movies2: Move constructor version------------
Constructor called
Move constructor called
Destructor called
Destructor called
我想我已经看到了一个赢家。正如在评论中所说的,在您的特定类中,您可以让编译器生成默认构造函数;一般来说,移动可能比复制更有效(请参阅更多)。
然而,考虑这第三种可能性:
Movies3.emplace_back(namex, ratingx);
那也没那么糟糕。看起来你正处于一个完美的世界,只有五个符合规则的成员。这意味着你可以遵守规则,什么也不做!旁注:不要挂断指针。三/五/零适用于你的对象可能需要手动管理的任何资源。例如,你可以有一个网络连接在对象销毁时必须进行适当握手的切分,或在关机时必须将机械臂返回到正确位置的切分。在您的问题上,字符串
可以解决您的问题。如果编译器可以利用移动字符串
的优势,则会有性能优势。编译器是智能的。也许它可以计算出所有他为您准备了。也许不是。@user4581301我不认为这取决于特定编译器的智能,因为标准很好地描述了隐式定义的移动构造函数必须做什么,但是,如果字符串实现有小字符串优化,移动操作比您预期的要复杂一些,但是啊。@MatG可观察行为是定义良好的,但只要可观察行为保持不变,编译器就可以做任何它想做的事情。编译器对我的代码所做的狡猾的蓝精灵经常让我感到惊讶。
------------Movies3: emplace_back version------------
Constructor called
Destructor called