Denstructor删除已被替换的成员

Denstructor deletes a member which is already replaced?

本文关键字:成员 替换 删除 Denstructor      更新时间:2023-10-16

我对C++世界还很陌生。。。我有一个关于C++中析构函数的问题。

如果有这样的类:

class TestClass {
public:
double *array;    
}

当我把一个数组的指针放在*array上,再放另一个并删除Testclass实例时,我就不能再访问旧的了?

它变成了一个错误:

int main() {
TestClass tc;
tc.array = new double[10];
double *array2 = tc.array;
tc.array[3]=9;
tc.array = new double[10];
delete &tc; // <------------------- this one.
std::cout<<array2[3]<<std::endl;
//    std::cout<<tc.array[3]<<array2[3]<<std::endl;
}

如果不存在CCD_ 2并且激活评论线(最后一行(,显示"09",(tc.array[3]!=array2[3]=>tc.array!=array2(这并不意味着tc.arrray不是*array2中的那个??

怎么了?

tc是一个函数范围的变量(在堆栈上分配(。它没有与new一起分配。你不能删除它。当函数返回时,它会自动释放

处理原始指针有些棘手,您的类可能会从使用std::vector<double>而不是原始指针中受益。另一个选择可能是std::unique_ptr<double[]>,它为您处理删除指针的操作。

也就是说,如果你想尝试一下,你应该知道什么时候删除什么。

tc是一个自动变量。您没有使用new创建tc,因此不应该使用delete。当它超出范围时(当程序离开创建tc的块时(,它将被销毁。

您还没有为TestClass定义析构函数,因此即使在tc被销毁后,array指向的内存仍将被分配。析构函数通常看起来是这样的:

~TestClass() {
delete[] array;
}

您还可以直接分配给tc的内部指针,这很危险。你应该有和new[]一样多的delete[],但在你的程序中不是这样,所以它会泄漏。您通常应该隐藏内部指针,这样在拥有它的对象没有控制权的情况下就无法重新分配它。

为了使手动内存管理正常工作,您应该考虑一些成员功能:

  • 复制构造函数
  • 移动构造函数
  • 复制分配运算符
  • 移动分配运算符
  • 破坏者

你可以在这里阅读更多关于这些的信息:三/五/零规则


这里有一个例子,说明了上面提到的5个成员函数加上一个默认构造函数、一个以指针为参数的转换构造函数和两个下标运算符的类的外观。

#include <iostream>
#include <utility> // std::move, std::swap, std::exchange
class TestClass {
public:
// default constructor
TestClass() :
array(nullptr) // member initializer
{
std::cout << "default ctorn";
}
// converting constructor - refuse lvalue pointers since we want to make sure
//                          that we "own" the pointer
TestClass(double*&& p) : array(p) {
std::cout << "converting ctor " << p << "n";
}
// copy constructing without knowledge about the size of the array isn't possible
TestClass(const TestClass&) = delete;
// move construction works though
TestClass(TestClass&& rhs) :
array(std::exchange(rhs.array, nullptr)) // steal pointer from rhs
{
std::cout << "move ctorn";
}
// copy assignment without knowledge about the size of the array isn't possible
TestClass& operator=(const TestClass&) = delete;
// move assignment works though
TestClass& operator=(TestClass&& rhs) {
std::cout << "move assignmentn";
// swap pointers with rhs - let rhs delete[] our current pointer
std::swap(array, rhs.array);
return *this;
}
~TestClass() { // destructor
delete[] array;
}
// subscripting support
double& operator[](size_t idx) { return array[idx]; }
double operator[](size_t idx) const { return array[idx]; }
private: // hide your raw pointer from direct access
double* array;
};
void printer(const TestClass& tc, size_t idx) {
// use const version of operator[] in the class
std::cout << tc[idx] << "n";
}
int main() {
TestClass tc; // default ctor
// use the converting constructor that creates a TestClass object from a pointer.
// It is then move assigned to tc
tc = new double[10];
tc[3] = 1;         // use the non-const version of operator[] in the class
printer(tc, 3);
double* a = new double[10];
// tc = a; // this won't work since we don't accept lvalues in assignment
tc = std::move(a); // make an xvalue to allow the assignment. "a" should not be
// delete[]-ed after this since we granted tc the possibillity
// to take ownership the pointer.
tc[3] = 2;
printer(tc, 3);
}