【问题标题】:Void pointer to a class object: Initialization inside a function指向类对象的无效指针:函数内部的初始化
【发布时间】:2017-04-26 08:45:58
【问题描述】:

我正在尝试创建一个指向类对象的 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);
}

【问题讨论】:

  • 除了数组是本地的这是您的核心问题之外,另一个问题是elemN 不是编译时常量表达式,因此将其用作数组的大小是不正确的。这很容易通过添加const 来解决。
  • new, void*。甚至 C++98 也有std::vector,C++11 也引入了std::shared_ptr&lt;&gt;。这段代码真的很痛苦,因为它在重新发明轮子,很糟糕。
  • 感谢您的建议。不幸的是,在这个问题中,我只能使用非常基本的工具。

标签: c++ class pointers void-pointers


【解决方案1】:

问题在于

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&lt;double&gt; ;)

#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 类的唯一目的是存储双精度而不是添加任何其他操作,那么就不管它,直接使用std::vector&lt;double&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-14
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多