指向 class 对象的空指针:函数内部的初始化
Void pointer to a class object: Initialization inside a function
我正在尝试创建一个指向 class 对象的空指针,并在函数内对其进行初始化。不幸的是,class 的数组成员无法转义该函数,即在初始化后无法访问它。
在下面的代码中,第一次调用打印位置(在初始化函数内)工作正常,但是,第二次从初始化函数外部调用打印位置失败。我有一种感觉,在初始化函数中创建的数组对象被销毁并且没有传递,但我不确定也不知道如何修复它。
如有任何帮助,我们将不胜感激。
#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 的唯一目的是存储双精度值而不添加任何其他操作,那么就不用管它了,直接使用 std::vector<double>
.
我正在尝试创建一个指向 class 对象的空指针,并在函数内对其进行初始化。不幸的是,class 的数组成员无法转义该函数,即在初始化后无法访问它。
在下面的代码中,第一次调用打印位置(在初始化函数内)工作正常,但是,第二次从初始化函数外部调用打印位置失败。我有一种感觉,在初始化函数中创建的数组对象被销毁并且没有传递,但我不确定也不知道如何修复它。
如有任何帮助,我们将不胜感激。
#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 的唯一目的是存储双精度值而不添加任何其他操作,那么就不用管它了,直接使用 std::vector<double>
.