C++ 构造函数/析构函数调用 &对动态创建的数据调用"new"是否会删除旧数据?
C++ Constructor/Destructor invocation & Does calling "new" on dynamically created data delete the old data?
在c++中,在保存new
'd数据的指针上调用new
是否会删除旧数据?
我想说它不会,而且会导致泄漏。在已经包含数据的指针上调用new,肯定只是将指针指向新数据,而我们将失去对旧数据的引用?
我问,因为我正在看这个页面,我注意到在构造函数中已经建议OP这样做:
MyString::MyString()
{
// A new, empty string contains zero characters plus a terminating zero.
nlength = 1;
nstring = new char[1];
nstring[0] = ' ';
}
MyString::MyString(const char *input)
{
// A new, copy of a C-string contains exactly the same number of characters in
// the C-string plus a terminating zero.
nlength = strlen( input ) + 1;
nstring = new char[ nlength ];
strcpy(nstring, input);
}
MyString::MyString(const MyString& S)
{
nlength = S.nlength; // we know this is correct!
nstring = new char[ nlength ];
strcpy( nstring, S.nstring );
}
//nstring is deleted in the destructor
MyString::~MyString()
{
delete[] nstring;
}
这对我来说似乎很奇怪。如果nstring
已经被定义,那么它会泄漏吗?没有?然而,这些都是构造函数,所以我猜这里的逻辑是每个实例只调用一次。这说得通。但是,如果我执行以下操作,会发生什么呢?
MyString myString("test");
myString = MyString("test2"); //is the destructor invoked here?
如果在重新赋值myString时调用析构函数,那么这一切对我来说都是有意义的。
总之,我想确认两件事:
- 如果您将
new
数据分配给已经具有new
数据的指针,那么这将泄漏,正确吗? - 重新分配对象时,是否调用了对象的析构函数?
你对指针的行为是正确的:当指针被重新分配时,内存将不会被释放。
代码的问题(我更改了变量的名称以避免混淆):
MyString x("test");
x = MyString("test2");
表示第二行不再调用x
的构造函数或析构函数。在c++中,每个对象只调用构造函数和析构函数一次。这段代码调用赋值操作符
序列调用将是:
- 用
"test"
调用x
的构造函数 - 使用
"test2"
调用未命名临时对象的构造函数。 - 用临时对象调用
x
的赋值操作符 调用临时对象的析构函数。 - 在当前作用域的末尾,调用
x
的析构函数。
赋值操作符应该或多或少这样定义:
const MyString &MyString::operator=(const MyString&o)
{
nlength = S.nlength; // we know this is correct!
delete []nstring;
nstring = new char[ nlength ];
strcpy( nstring, S.nstring );
return *this;
}
这段代码当然不是异常安全的。如果这个new
失败了会发生什么?物体会碎的!
const MyString &MyString::operator=(MyString o)
{
swap(*this, o);
return *this;
}
这被称为copy-n-swap习惯用法,或者类似的东西。当运行上面的点3时,对这个operator=
的调用顺序将是:
- 调用
o
的复制构造函数,传递临时的。 - 交换
o
和this
的值 - 调用
o
的析构函数,这将删除第一个分配("test1"
)。
不,任何通过调用new
或new[]
返回的指针必须被相应的调用delete
或delete[]
释放。
int* x = new int;
x = new int; // Memory leak!
c++中的new
是一个返回在堆上分配的对象的操作符。它不关心你赋给它什么。唯一重要的是,通过new
返回的对象最终被传递给delete
操作符。
In C++, does calling new on a pointer that holds new'd data delete the old data?
。您必须delete
分配的内存。
If the destructor is invoked upon reassigning myString then it all makes sense to me.
MyString myString("test");
myString = MyString("test2"); //is the destructor invoked here?
你贴的代码很有趣。除了建筑之外,还要完成一项作业。您的类的问题是它缺少用户定义的赋值操作符(至少没有显示),因此是内存泄漏。
在任何其他成员函数之前调用构造函数。因此,nstring
不可能已经指向一些已分配的内存。
正如你所说,x = new int;
不delete
任何x
之前指向的(如果有的话)。
线路:myString = MyString("test2");
呼叫myString.operator=( MyString("test2") );
。你说得好像你认为它摧毁了MyString
,然后建造了一个新的,但这并没有发生。它只是一个函数,我们称之为复制赋值操作符,你应该实现这个函数。
表达式MyString("test2")
中包含了一个构造和一个销毁,但这并不影响myString
。
new
不释放预分配的内存。如果您在释放资源之前使用new
,那么将获得内存泄漏。在您的示例中,执行myString = MyString("test2")
确实会导致内存泄漏,因为复制赋值操作符(或移动赋值操作符,具体取决于编译器版本)不会清除nstring
已经占用的内存。这两个函数都是由编译器提供的,因为您没有自己创建它们,它们的工作(默认情况下)只是复制(或移动)成员,而不考虑内存管理。
- 使用JsonCpp将数据返回到带有pybind11的python会在python调用中产生Symbol not foun
- 调用在 HXX 文件中声明的静态数据成员
- 使用 pybind11 调用 Python 函数时避免复制输入数据
- 从C++调用 Python 脚本以持续流式传输数据
- 从 cpp lib 调用函数时的数据类型转换
- C++:如何通过 curl 调用使用 HTTP post 请求发送二进制数据(protobuf 数据)
- 使用ifstream时,被调用文件中的数据不会打印
- 通过外部分配的数据调用特征 GEMM
- 调用Main将替换矢量对象并覆盖数据
- 模板 使用数据数组调用函数时扩展参数包
- 只需调用对象即可获取对象数据
- 如果两个线程调用同一个函数,但函数中的所有变量都是局部变量,我还需要担心线程之间共享数据吗?
- 在模板化数据结构上调用 begin() 或 end()
- 在向量上调用 clear() 实际上不会删除 data() 中的数据?
- 通过 lambda 调用成员函数时意外未初始化的数据
- 如何使用模板根据数据类型调用函数?
- C++函数调用后丢失的数据
- 用内存中的Fortran数据调用C代码
- C++ 构造函数/析构函数调用 &对动态创建的数据调用"new"是否会删除旧数据?
- 使用派生类的数据调用基类的方法:有没有一种优雅的方法可以做到这一点?