C++;如果不存在原始指针变量,则移动构造函数与复制构造函数 学习C++和所有关于构造函数(复制,移动)的东西,我想知道正确的/聪明的/有效的方法是什么。 以下场景: 我有一个班级电影,包含标题,评级和计数器。每次实例化该类的对象时,我都希望将该对象放入对象数组(称为Movies)中。因此,如果我看了3部电影,我的数组将包含类电影的三个实例。因为我的电影类不包含原始指针,所以我想知道使用copy或move将特定电影添加到我的收藏中是否会有性能上的差异。我希望我的想法是清楚的,以便更好地理解以下代码。希望有人能启发我。谢谢,

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;

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;

    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