我试图理解C ++中更好的函数调用。我有以下代码:
class A{
public:
A() { cout << "hello\n"; }
A(const A& obj) { cout << "world\n"; }
~A() { cout << "bye\n"; }
virtual void print() { cout << "a\n"; }
};
A foo(A aobj)
{
aobj.print();
return aobj;
}
int main(){
A a,b,c;
foo(a);
system("pause");
return 0;
}
输出为:
hello //from calling A's default constructor
hello
hello
world //because we pass 'a' by value in funtion foo so the copy constructor is used
a
world //because foo returns by value so the copy constructor is used again
bye //?
bye //?
有人可以解释一下为什么析构函数最后被调用两次吗?是因为两个拷贝构造函数调用了吗?
谢谢您的时间!
答案 0 :(得分:2)
“再见”被打印5次,因为~A()
也被称为5次。对于对象a
,b
,c
,析构函数称为对象。然后,当您按值传递a
时,会在foo
中创建一个副本,然后将其销毁。最后,foo的返回类型是A
的实例,当执行移至下一行时,该实例将被销毁。因此,~A()
总共将被调用5次。
在对象生存期结束时调用析构函数以释放该对象使用的内存。
答案 1 :(得分:1)
创建了5个对象,因此将输出5个“ bye”。
但是,只有2个对象超出范围,并且在调用system("pause")
之前({1)创建的2个对象)被破坏。其他3个对象超出范围并在对foo()
的调用后 被破坏。因此,如果在应用程序退出时控制台窗口关闭,您可能没有机会看到这3个“再见”。
您可以通过引入另一个生存期较短的范围来强制这3个对象更快地超出范围,如下所示:
system("pause")
或者这样:
int main(){
{
A a,b,c;
foo(a);
}
system("pause");
return 0;
}
现在,所有5个对象都将超出范围并在对void doIt(){
A a,b,c;
foo(a);
}
int main(){
doIt();
system("pause");
return 0;
}
的调用之前被破坏。
答案 2 :(得分:-2)
尝试一下:
class A {
public:
A() { cout << "Default ctor → A::A()\n"; }
~A() { cout << "Default dtor → A::~A()\n"; }
A(const A&) {
cout << "Copy ctor → A::A(const A& rhs)\n";
}
A& operator=(const A& rhs) {
cout << "Copy operator= → A& A::operator=(const A& rhs)\n";
return *this;
}
A(const A&&) {
cout << "Move ctor → A::A(const A&& rhs)\n";
}
A& operator=(const A&& rhs) {
cout << "Move operator= → A& A::operator=(const A&& rhs)\n";
return *this;
}
};
还要获取 Effective Modern C ++ 的副本,并阅读第17项:了解特殊成员函数的生成。