我正在阅读Marshall Cline的C ++ FAQ。
目前正在使用第10.5点的代码。
我有这个:
class Fred
{
public:
Fred();
Fred(int x, int y)
{
std::cout << "Fred with two ints\n" << std::endl;
};
};
int main()
{
std::vector<Fred>(3, Fred(4,5));
return 0;
}
我希望看到“Fred with two oftts”打印3次 - 但它只打印一次。 为什么 - 是不是被调用了3次?
答案 0 :(得分:6)
这是您正在调用的vector
构造函数的签名:
vector( size_type _Count, const Type& _Val, const Allocator& _Alloc = Allocator() );
Fred(4,5)
调用您定义的构造函数一次,并通过引用传递创建的实例vector<Fred>
构造函数。然后,将[创建的实例]复制3次到向量。使用(默认)复制构造函数执行复制操作;所以你的构造函数不会被多次调用。
答案 1 :(得分:2)
当您编写Fred(4,5)时,您将调用一次用户定义的构造函数。这将被传递给vector的构造函数,该构造函数将其复制3次为3个Freds。这使用您的复制构造函数,而不是您的默认或自定义构造函数。如果您不编写自己的复制构造函数,则会隐式添加一个,分配操作也是如此。下面,我添加了一个复制构造函数和赋值操作来显示幕后添加的内容:
class Fred
{
public:
Fred(); // default constructor
Fred(int x, int y) // custom constructor
{
std::cout << "Fred with two ints\n" << std::endl;
};
Fred(const Fred&); // copy constructor
Fred& operator=(const Fred&); // assignment operator overload
};
复制构造函数: 弗雷德(const Fred&amp;); 当向量构造函数将Fred复制到包含Freds的3中时,会调用什么。如果你自己实现它,你会看到它被调用3次。这是一个完整的演示:
#include <iostream>
#include <vector>
using namespace std;
class Fred
{
private:
int x,y;
public:
Fred() // default constructor
{
cout << "Fred's default constructor\n";
}
Fred(int x, int y) // custom constructor
{
cout << "Fred's custom constructor\n" << std::endl;
};
Fred(const Fred& rhs) // copy constructor -- NOTE rhs stands for "right-hand-side"
:x(rhs.x),y(rhs.y)
{
cout << "Fred's copy constructor\n";
}
Fred& operator=(const Fred& rhs) // assignment operator overload
{
if(&rhs != this)
{
cout << "Fred's assignment overload\n";
x = rhs.x;
y = rhs.y;
}
return *this;
}
};
int main(int argc, char** argv)
{
Fred fred; // calls default constructor
vector<Fred> myFreds(3,Fred(4,5)); // calls custom constructor, then copy constructor 3 times.
fred = myFreds[0]; // calls assignment overload
return 0;
}
输出:
Fred的默认构造函数
Fred的定制构造函数
弗雷德的复制构造函数
弗雷德的复制构造函数
弗雷德的复制构造函数
弗雷德的任务超载
如果禁用复制构造函数和赋值重载,则在尝试使用它们时会出现错误。如果你使用C ++ 11,如果你可以通过如上所述声明它们来禁用它们,然后是= delete;
Fred(const Fred&) = delete;
如果你不使用C ++ 11,你可以通过私下声明它们来有效地禁用它们:
private:
Fred(const Fred&); // NOTE: Don't define this function.
一旦禁用,您将看到您的程序不再编译,因为它正在尝试访问被禁用的功能。它只为你编译,因为你允许通过不自己定义它们来隐式添加它们。