gpt4 book ai didi

c++ - 指向类对象的空指针 : Initialization inside a function

转载 作者:搜寻专家 更新时间:2023-10-31 00:54:57 25 4
gpt4 key购买 nike

我正在尝试创建一个指向类对象的 void 指针,并在函数内对其进行初始化。不幸的是,该类的数组成员无法转义该函数,即在初始化后无法访问它。

在下面的代码中,第一次调用打印位置(在初始化函数内)工作正常,但是,第二次从初始化函数外部调用打印位置失败。我有一种感觉,在初始化函数中创建的数组对象被销毁并且没有传递,但我不确定也不知道如何修复它。

如有任何帮助,我们将不胜感激。

#include <iostream>
#include <iomanip>
#include <string>


class Atoms
{
double * positions;
int nAtoms;

public:
// Standard constructor prividing a pre-existant array
Atoms(int nAtoms, double * positionsArray)
{
this->nAtoms = nAtoms;
this->positions = positionsArray;
}

// Print positions to screen
void print_positions()
{
std::cout<< "nAtoms: " << this->nAtoms << std::endl;
int nDim = 3;
for (int i = 0; i < nAtoms; i++)
{
for (int j = 0; j < nDim; j++)
{
std::cout << std::setw(6) << this->positions[i * nDim + j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}

};


void initialize_Atoms_void_pointer(void ** voidAtomsPointer)
{
//Create a new instance of Atoms by a pointer
int numAtoms = 5;
int numDim = 3;
int elemN = numAtoms * numDim;
double data_array[elemN];

for (int i = 0; i < numAtoms; i++)
for (int j = 0; j < numDim; j++)
{
data_array[i * numDim + j] = i * numDim + j + 10;
}
Atoms *atoms = new Atoms(numAtoms, data_array);

// Set the vPointer that the void pointer points to a pointer to Atoms object
*voidAtomsPointer = static_cast<void *>(atoms);

//Test call
std::cout << std::endl << "Initializing atoms" << std::endl;
static_cast<Atoms *>(*voidAtomsPointer)->print_positions();
}


void print_Atoms_pointer_positions(void * voidAtomsPointer)
{
//Cast the pointer as an atoms pointer
Atoms *atomsPointer = static_cast<Atoms *>(voidAtomsPointer);

atomsPointer->print_positions();
}

int main()
{
//Use the initializer function for getting a pointer
void *testVoidAtomsPointer;

initialize_Atoms_void_pointer(&testVoidAtomsPointer);
print_Atoms_pointer_positions(testVoidAtomsPointer);
}

最佳答案

问题是在

Atoms *atoms = new Atoms(numAtoms, data_array);

data_array是一个局部数组,在initialize_Atoms_void_pointer时被销毁退出。

不是复制原始指针,而是在 Atoms 中进行新分配的构造函数并复制内容:

Atoms(int nAtoms, double * positionsArray)
{
this->nAtoms = nAtoms;
this->positions = new double[nAtoms];
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}

~Atoms()
{
delete[] this->positions;
}

更安全的实现方式包括使用 std::unique_ptr ,它将在 Atoms 时自动为您取消分配内存被销毁:

#include <memory>

class Atoms {
std::unique_ptr<double[]> positions;
// ...

public:
Atoms(int nAtoms, double * positionsArray) :
positions(new double[nAtoms]) {
this->nAtoms = nAtoms;
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}

// ...
};

您还需要检查是否 nAtoms为0或负数,如果输入数组为null等,但我认为它不在问题范围内。

如果你需要访问裸指针,你可以使用positions.get()方法(不要尝试删除它,否则您的应用程序将因双重删除而崩溃)。

更新

当然,另一个更直接的解决方案是简单地使用 std::vector<double>相反 ;)

#include <vector>

class Atoms {
std::vector<double> positions;
// int nAtoms; -- no longer necessary

public:
Atoms(int nAtoms, double * positionsArray) :
positions(nAtoms) {
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}

// ...
};

如果你需要访问裸指针,你可以使用positions.data()方法(不要尝试删除它,否则您的应用程序将因双重删除而崩溃)。可以使用 positions.size() 检查原子数.

如评论中所述,如果 Atoms 的唯一目的是class是存double不加其他操作,那就不管了,直接用std::vector<double> .

关于c++ - 指向类对象的空指针 : Initialization inside a function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43629171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com