为什么构造函数被调用两次
Why constructor is being called twice
我不明白怎么constructors work
?
在这里,我声明了一个对象obj2
。它调用构造函数abc()
,这完全没问题。
但是当我分配时
obj2 = 100
为什么编译器允许将整数初始化为类对象?如果它允许,那么它如何销毁对象,然后它如何调用另一个参数化构造函数。
现在我有另一个问题,为什么destructor
因为有two
对象而只调用一次?
我还有一个疑问是,编译器与default constructor
not doing anything
,那么为什么默认构造函数是required
?
class abc{
public:
int a, b;
abc()
{a = 0; b = 0;}
abc(int x)
{a = x;}
~abc()
{std::cout << "Destructor Calledn";}
};
int main()
{
abc obj1;
cout << "OBJ1 " << obj1.a << "..." << obj1.b << "n";
abc obj2;
cout << "OBJ2 " << obj2.a << "..." << obj2.b << "n";
obj2 = 100;
cout << "OBJ2 " << obj2.a << "n";
system("pause");
return 0;
}
output:
OBJ1 0...0
OBJ2 0...0
Destructor Called
OBJ2 100
但是当我分配 obj2 = 100 时,编译器如何允许将整数初始化为类对象?
这是因为当您执行以下操作时:
obj2 = 100;
这将首先调用 abc(int x)
来生成类的对象,然后调用默认的复制赋值运算符(因为没有提供用户定义的(将值 100 分配给现有obj2
。分配后,临时对象将被销毁。
如果不希望产生这种效果,请将构造函数标记为explict
以避免隐式调用。
explicit abc(int x) {
//do something
}
obj2 = 100;
您定义了一个采用int
的构造函数。 这允许从 int 到 abc
的隐式转换。 这需要创建一个新对象。 它不只是通过调用构造函数神奇地在现有对象中设置字段;构造函数构造新对象。
编辑:来自@Steve杰索普的正确事件顺序
创建一个新实例,然后将副本分配给原始实例,然后销毁临时(而不是原始实例(。复制赋值确实神奇地在现有对象中设置了这两个字段。
让我们表演和讲述,让我们为所有特殊成员进行乐器:
#include <iostream>
class abc{
public:
int a, b;
abc()
{ std::cout << "Default constructorn"; a = 0; b = 0;}
abc(int x)
{ std::cout << "Int constructorn"; a = x;}
abc(abc const& other): a(other.a), b(other.b)
{ std::cout << "Copy constructor (" << a << ", " << b << ")n"; }
abc& operator=(abc const& other) {
std::cout << "Assignment operator (" << a << ", " << b << ") = (" << other.a << ", " << other.b << ")n";
a = other.a;
b = other.b;
return *this;
}
~abc()
{std::cout << "Destructor Calledn";}
};
int main()
{
abc obj1;
std::cout << "OBJ1 " << obj1.a << "..." << obj1.b << "n";
abc obj2;
std::cout << "OBJ2 " << obj2.a << "..." << obj2.b << "n";
obj2 = 100;
std::cout << "OBJ2 " << obj2.a << "n";
return 0;
}
我们得到这个输出:
Default constructor
OBJ1 0...0
Default constructor
OBJ2 0...0
Int constructor
Assignment operator (0, 0) = (100, 0)
Destructor Called
OBJ2 100
Destructor Called
Destructor Called
因此,让我们将它们与行源进行协调:
int main()
{
abc obj1;
// Default constructor
std::cout << "OBJ1 " << obj1.a << "..." << obj1.b << "n";
// OBJ1 0...0
abc obj2;
// Default constructor
std::cout << "OBJ2 " << obj2.a << "..." << obj2.b << "n";
// OBJ2 0...0
obj2 = 100;
// Int constructor
// Assignment operator (0, 0) = (100, 0)
// Destructor Called
std::cout << "OBJ2 " << obj2.a << "n";
// OBJ2 100
return 0;
// Destructor Called
// Destructor Called
}
你基本上拥有了一切,让我们检查一下惊喜。
第一个惊喜:即使obj2
稍后更改值abc obj2;
仍将在声明点调用默认构造函数。
第二个惊喜:obj2 = 100
其实是obj2.operator=(abc(100));
的意思,即:
- 从
abc(100)
构建临时(未命名(abc
- 将其分配给
obj2
- 在继续下一条语句之前销毁临时语句
第三个惊喜:析构函数在范围的末尾调用,就在右括号}
之前(是的,在return
之后(。由于您使用的是system("pause")
我假设您在 Windows 上 =>尽管幸运的是它们在您结束暂停后被调用,因此您的控制台 Windows 在它们出现的那一刻眨眼间消失了。您可以从更永久的控制台启动程序,也可以使用额外的作用域:
int main () {
{
// your code here
}
system("pause");
return 0;
}
这是因为有构造函数可以接受int
类型的参数。通过调用默认复制分配,将临时创建的对象复制到obj2
。
若要避免此类转换,请将构造函数标记为显式。
你的析构函数被调用了 3 次,由于暂停,你看不到它。
- 用相同的参数声明两个构造函数的最偶像化的方法是什么?
- pair的两个构造函数几乎相同,为什么不生成构建错误?
- 为什么<T> LLVM 中的预期为 Expect&&... 实现两个构造函数<T>?
- 为什么我的类只适用于两个构造函数 C++
- 两个构造函数(带和不带参数),没有输入 -> 没有参数运行。跳过上述类中的构造函数
- 类介绍 (c++) 项目希望我们创建两个构造函数,但它们都不需要任何参数 - 我应该在这里做什么?
- 除了两个构造函数外,C++库导入也可以工作
- 两次构造对象
- 在两个构造函数之前将我的静态数据成员在 CPP 文件中初始化为 0
- 如何有条件地在具有相同签名的两个构造函数之间切换
- RAII 在两个构造函数之间进行选择的方式
- 调用对数组引用两次的函数
- std::make_shared在VS2012中进行了两次构造函数调用
- 具有两个构造函数的抽象类
- 如何在c++中实现二次构造函数
- 这两个构造函数调用之间的区别
- 为什么在我的程序中调用两个构造函数
- 组合复制和移动的两个构造函数
- 为什么这两个构造函数一起不会产生歧义错误?
- C++两次传递函数指针导致问题