【问题标题】:Pass a pointer to a class function in c++在 C++ 中传递指向类函数的指针
【发布时间】:2015-12-01 09:27:04
【问题描述】:

我正在学习 C++ 课程,所以我尝试了不同的方法来适应这些课程。这里我试图传递一个指向类函数的指针:

class Pointerss{
    int size;
public:
    Pointerss(int);
    void f();
    int *a;
};

Pointerss::Pointerss(int siz){
    size = siz;
}

void Pointerss::f(){
    cout<<"Size is:"<<size<<"\n";
    for (int i=0; i<size; ++i) {
       cout<<"a is:"<<a[i]<<"\n";
    }
}
int main() {
    int size = 5;
    Pointerss dd (size);
    Pointerss * p = new Pointerss(size);
    p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
    p->a;
    dd.f();
    return 0;

}

所以“大小”由构造函数初始化,当调用“f()”时,打印正确的数字。但是当我将“p”分配给“a”(“p->a”)然后调用“f()”时,会打印一些随机数。我的电脑打印:

Size is:5
a is:0
a is:0
a is:1
a is:0
a is:1606416856
Program ended with exit code: 0

“a”和“size”有什么区别,我应该怎么做才能将指针传递给函数?

【问题讨论】:

  • 我可以看到至少 3 个不同的问题。
  • 这将被关闭和删除,但你需要阅读一个初学者C++ book,它教你什么是“p->a”(当然不是赋值)以及如何做变量初始化和赋值。
  • Pointerss* p = new Pointerss(size) 分配单个元素,而不是数组。所以p[1]=2 超出了访问范围,UB 也是。
  • 这里也有很好的教程:cplusplus.com/doc/tutorial

标签: c++ class pointers


【解决方案1】:

打印随机数是因为 Pointerss::f 取消引用您从未初始化过的 dd.a。取消引用未初始化的指针会导致未定义的行为。

这不是您遇到的唯一错误。您还为p 指向的单个Pointerss 对象分配内存,然后继续在p[1..4] 中构造指向未分配内存的对象。这也会导致未定义的行为。

第三,你永远不会释放你用new分配的内存。

【讨论】:

    【解决方案2】:

    第一步是理解指针。当您创建int* 时,您只保留内存来存储指针本身。您不会为任何int 保留内存。因此,当您尝试打印整数时,您只会得到随机数(或者可能是程序崩溃)。

    所以你的类不能保存任何整数。您需要更改它,以便在构造函数中保留内存并在析构函数中释放它。

    class Pointerss{
        int size;
    public:
        Pointerss(int);
        ~Pointerss();
        void f();
        int *a;
    };
    
    Pointerss::Pointerss(int siz){
        size = siz;
        a = new int[size];  // Reserve memory for size integers
    
        // Do some initialization if needed, e.g.
        for (int i=0; i < size; i++) a[i] = i;
    }
    
    Pointerss::~Pointerss(){
        delete[] a;         // Release the memory again
    }
    
    void Pointerss::f(){
        cout<<"Size is:"<<size<<"\n";
        for (int i=0; i<size; ++i) {
           cout<<"a is:"<<a[i]<<"\n";
        }
    }
    

    此外,您不能创建指向类实例的单个指针,即

    Pointerss * p = new Pointerss(size);
    

    然后像这样使用它

    p[0]=1; p[1]=2; p[2]=3; p[3]=4; p[4]=5;
    

    因为它在 5 个不同的实例上运行。

    最后是代码:

    p->a;
    

    什么都不做!

    你可以的

    p->a[0] = 5;
    

    但不清楚您要做什么。

    请注意,dd 和 p 指的是您的类的两个不同实例,因此更改 *p 中的某些内容根本不会更改 dd。

    如果你这样做了:

    Pointerss *p = &dd;
    

    那么*p 和 dd 将是同一个实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-16
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 1970-01-01
      相关资源
      最近更新 更多