我有以下代码:
#include <iostream>
#include <string>
using namespace std;
class Uno {
public: Uno() { cout << "X"; }
};
int main()
{
Uno u;
Uno k=u;
return 0;
}
所以根据我的理解,代码Uno k=u;
会创建一个u的副本。似乎构造函数被调用了两次。我期待“XX”,但程序只输出“X”。你能解释一下发生了什么吗?
谢谢
答案 0 :(得分:3)
这是怎么回事:
Uno k = u;
是(复制 - )初始化,它从Uno
对象k
复制构造Uno
对象u
。复制构造意味着调用复制构造函数(在这种情况下由编译器隐式生成),而不是默认构造函数。
这就是为什么在k
初始化期间不输出您输出的消息:您的构造函数不会被调用;相反,调用另一个(隐式生成的)构造函数。
另请注意,上述声明不通常与此相同:
Uno k;
k = u;
在最后一个片段中,表达式k = u
是赋值,而不是初始化。虽然这两个构造都使用=
符号,但您不应该让它混淆。
答案 1 :(得分:1)
k
,该构造函数不输出X
。
尝试添加此内容:
Uno(const Uno&) { cout << "Y"; }
您应该看到XY
输出。
答案 2 :(得分:1)
在这种情况下,我认为没有调用构造函数,因为你没有创建一个新对象;相反,您正在将旧对象复制到其他位置。
但是,由于你没有使用指针,它们应该是独立的;改变为一个不会影响另一个。
代码第二次不运行构造函数,因为它没有构建新的东西。想象一下,在创建它之后,你已经对你的一个领域做了一些改变。再次调用构造函数不会复制u,因此C ++不会这样做。这有点像复制一张照片 - 这样做不会让你的相机两次熄灭,因为这会产生不同的画面;相反,你通过复印机运行它,这是不同的。
编辑:正如我所知,它确实运行了一个构造函数,而不是你编写的那个。假设我的比喻中的相机有一个内置复印机,当然不会闪光。
答案 3 :(得分:1)
这是因为你的类没有复制构造函数。如果没有创建复制构造函数,则C ++调用默认构造函数。这显然没有cout&lt;&lt;“X”线。
Uno u; // your constructor called, --> X to output
Uno k = u; // default copy constructor called
但是,如果您没有成员变量,则复制构造函数没有意义。
所以让我们说这就是你想要的:
#include <iostream>
#include <string>
using namespace std;
class Uno
{
public:
string text;
// constructor
Uno()
{
text = "X";
cout << text;
}
// copy constructor
Uno(const Uno &o)
{
text = o.text;
cout << text;
}
};
int main()
{
Uno u; // call constructor -> X
u.text = "Y"; // change text in constructed object
Uno k=u; // create new object via calling copy constructor --> Y
// so u.text copied to k.text
return 0;
}
我推荐learncpp.com篇文章,它们非常有用并且简单易懂。
有关复制构造函数和赋值运算符的更多信息: http://www.learncpp.com/cpp-tutorial/911-the-copy-constructor-and-overloading-the-assignment-operator/
答案 4 :(得分:0)
戴上我的笨拙的帽子......除非你明确告诉编译器,否则默认情况下你总是有复制构造函数:
Uno(const Uno & other);
和赋值运算符:
Uno & operator=(const Uno & other);
你是否要求他们。如果您没有定义任何其他构造函数,那么您还将获得默认构造函数:
Uno();
由于您已经定义了无参数构造函数,因此将使用您的构造函数而不是最后一个默认构造函数。
定义变量时:
Uno u;
您的构造函数用于初始化对象实例。当你完成任务时:
Uno k=u;
使用赋值运算符。
您可能会问,我如何防止复制或分配对象?声明它们是私有的,不实现它们:
class Uno
{
private:
Uno(const Uno &);
Uno & operator=(const Uno &);
...
};