c++ 在for_each循环中不调用复制构造函数

yqyhoc1h  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(145)

我试着学习C++,我在练习for_each循环和循环。我正在写一个简单的例子,其中一个向量的成员是在for_each循环中构造的。然而,复制构造函数并没有在我期望的地方被调用。代码工作,但我不明白为什么?我也试着删除了move构造函数。但是,当我创建l时,

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Point
{
  int x;
  int y;
public:
    Point (int x, int y):x (x), y (y)
  {
    cout << "paramterized constructor" << endl;
  }
  Point () = default; 
  Point (const Point & p)
  {
    cout << "copy constructed" << endl;
    x = p.x;
    y = p.y;
  }
  void print () const
  {
    cout << x << " " << y << endl;
  }
};

int
main ()
{

  std::vector < Point > my (5); 
  cout << "vector created" << endl;
  int count = 0;
  auto l = Point (5, 6);//RH paramterized constructed and then copy constructed to left? 
  std::for_each (my.begin (), my.end (),[&](Point & p)
         {
            p = Point (++count, count);//p not copy constructed?
            count++;
         });        
  std::for_each (my.begin (), my.end (),[](const Point & p)
         {
            p.print ();
         });

  return 0;
}

输出

default constructor
default constructor
default constructor
default constructor
default constructor
vector created
paramterized constructor
copy constructed
paramterized constructor
paramterized constructor
paramterized constructor
paramterized constructor
paramterized constructor
1 0
3 2
5 4
7 6
9 8
rjjhvcjd

rjjhvcjd1#

你什么都没做。建设一次。这就是“复制分配”。

p = Point(++count, count);

我们不能构造p,因为它已经存在。Construction意味着把某物带入存在。作为一个现实世界的类比,这就像如果我带你到一个完成的房子,然后宣布,我将建立确切的房子在确切的地段。
相反,它首先调用Point(int, int)构造函数(因为你给它传递了两个整数),然后我们用一个复制赋值操作符将这个临时变量 * 赋值 * 给p。复制赋值运算符,像C++中的许多东西一样,如果可能的话,会自动生成,除非你自己创建一个。创建自己的语法如下。

Point& operator=(const Point& p) {
    x = p.x;
    y = p.y;
    return *this;
}

按照惯例,我们返回*this作为复制赋值的引用,因此赋值链(a = b = c)就像C程序员期望的那样工作。
如果你定义了一个复制构造函数,你还应该定义一个析构函数和一个复制赋值运算符。如果要实现移动构造,还需要实现移动分配。这被称为Rule of Zero/Three/Five,我强烈建议你阅读链接的问题和答案,因为它包含了很多有价值的信息。
您还需要研究the copy-and-swap idiom,它可以使实现复制赋值更容易(并防止它和复制构造函数之间的代码重复)。
最后,它被称为“/三/五规则”是有原因的。大多数情况下,“我应该实现这五种方法中的哪一种”的答案是“零”。你的类包含两个整数。它不做任何复杂的资源分配,也不使用原始指针。所以对你来说最好的情况就是不要实现它们中的任何一个。C
将为您提供以下所有内容,对于您的Point类(以及C++中不使用原始指针的 * 许多 * 类),它将是正确的。

  • Destructor
  • 复制构造函数
  • 复制赋值
  • 移动构造函数
  • 移动赋值

相关问题