为什么在删除对象之前调用复制构造函数
Why is the copy constructor being called before deleting the object?
我有以下类,其中包括一个复制构造函数:
头文件:Fred.h
namespace foo {
class Fred {
private:
int _x;
int _y;
public:
Fred(); // Default constructor
Fred(Fred const &other); // Copy constructor
Fred(int x, int y); // Regular parameters
~Fred(); // Destrcutor
};
}
实现文件:Fred.cpp
#include "Fred.h"
#include <iostream>
foo::Fred::Fred(){
_x = 0;
_y = 0;
std::cout << "Calling the default constructorn";
}
foo::Fred::Fred(Fred const &other){
_x = other._x;
_y = other._y;
std::cout << "Calling the copy constructor";
}
foo::Fred::Fred(int x, int y){
_x = x;
_y = y;
std::cout << "Calling the convenience constructorn";
}
foo::Fred::~Fred(){
std::cout << "Goodbye, cruel world!n";
}
当析构函数超出范围时,我希望看到它被调用,相反,复制构造函数被调用,然后析构函数被调用。为什么要创建副本?我是在泄露记忆吗?
using namespace foo;
int main(int argc, const char * argv[])
{
{
Fred f2 = *new Fred();
} // I was expecting to see a destructor call only
return 0;
}
这是因为您使用的是内存泄漏运算符*new
。
分配有new
的对象永远不会自动删除;仅通过明确使用CCD_ 3。您的代码动态地分配一个对象,将其复制到f2
,然后丢失指向该动态对象的唯一指针。
如果你只是想创建一个本地对象:
Fred f2;
当您实际需要动态分配时(换句话说,如果对象需要超过当前范围),请始终使用RAII对象,如智能指针,以避免内存泄漏。例如:
std::unique_ptr<Fred> f2(new Fred); // C++11 - no "delete" needed
auto f2 = std::make_unique<Fred>(); // C++14 - no "new" or "delete" needed
是的,代码泄漏内存:new Fred()
在堆上分配了一个对象,但代码不保存返回的指针,也不删除该对象。
调用复制构造函数的原因是f2
的创建复制了参数,就像它是一样
Fred f2(*new Fred());
您可能想写的是:
Fred f2 = Fred();
由于Fred
有一个用户定义的默认构造函数,您可以将其缩短为:
Fred f2;
创建副本是因为您正在复制由以下表达式创建的动态分配对象:
new Fred();
进入Fred f2
:
Fred f2 = *new Fred(); // f2 is a copy of RHS object
永远不会调用动态分配对象的析构函数。这是内存泄漏。将只调用f2
的析构函数。
请参阅此演示。
C++默认情况下在堆栈上分配变量。当你写一个像Foo* foo = new Foo;
这样的句子时,你要做的是在堆栈上分配一个指针,该指针指向你在堆上分配的新对象
您的代码忘记释放指针指向的对象所使用的内存,因此该对象永远不会被释放,及其析构函数永远不会被调用。
我建议你检查一下这个线程:我应该什么时候在C++中使用新关键字?
通过取消对堆上新创建的对象的引用并将其分配给Fred f2
,您可以简单地调用复制构造函数。它与相同
Fred f1;
Fred f2 = f1;
此外,您"丢失"了指向堆上对象的指针,该指针不会自动删除-->内存泄漏。
如果您没有使用RAII(但应该),则需要手动清除。看起来像:
using namespace foo;
int main(int argc, const char * argv[])
{
{
Fred* pF2 = new Fred(); // keep the pointer to manually delete
}
// no destructor call even though scope is left --> delete manually
delete pF2;
pF2 = 0;
return 0;
}
- 当从函数参数中的临时值调用复制构造函数时
- 为什么调用复制构造函数而不是移动构造函数?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 编译器调用复制运算符而不是移动运算符
- push_back std::vector,则重复调用复制构造函数
- 为什么调用复制构造函数来构造空unique_ptr向量?
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 我打算调用initializer_list构造函数,如果存在,则事先调用复制构造函数:为什么?
- C++ - 从移动分配运算符调用复制分配
- 构造函数初始值设定项列表未调用复制构造函数
- 为什么在我的代码中调用复制构造函数而不是移动构造函数?
- std::map 在 [] 上调用默认构造函数,在 insert() 上调用复制构造函数
- 通过引用传递对象时是否调用复制构造函数?
- 如果函数按值传递并按值返回,将调用复制构造函数多少次
- 为什么要抛出引用调用复制构造函数的异常?
- 为什么即使参数标记为"const",也会调用复制构造函数?
- Clang-Tidy:移动构造函数通过调用复制构造函数来初始化类成员
- 为什么当我添加一个不同的对象(复制构造函数中的参数)时调用复制构造函数?
- 为什么调用复制构造函数,当我只返回对象 c++ 的引用时
- 为什么在下面的代码中调用复制构造函数两次