簡體   English   中英

如何從類成員函數返回指針,例如 size_t * class :: function(); 並使用類析構函數 ~size_t*class::function();

[英]How do I return a pointer from a class member function e.g. size_t * class :: function(); and use a class destructor ~size_t*class::function();

我正在學習 C++ 中的類/析構函數,並且需要從類成員返回指針:

size_t * classname :: function();

但它不起作用。

我的邏輯是聲明一個類變量,例如classname * p_p = classfunction(data); 應該訪問類成員:

size_t * classname :: classfunction(data)
{
    //... do something ... 
    new p_p;

    return p_p;
}

因此,每次調用類的成員函數時,理論上的指針地址都會返回到main()變量p_p 或者應該但不應該並且程序以某種方式崩潰但甚至不確定在哪一點。

沒有編譯器警告或錯誤,調試器不會在任何地方停止,而且我根本沒有發現從類成員函數返回指針的任何內容,也沒有發現它是不允許的或什么的。

此外,如果有一種語法可以從類成員函數返回指針,我將需要一種語法來刪除“ new p_p ”。

所以我的問題是:它應該工作,我將如何運行它,或者為什么它可能不起作用或被禁止? 在我的邏輯中,它應該是一種正確的方式,但我可能以某種方式錯了,並且類不完全支持此功能。

編輯:

感謝您的回答和評論,我得到了班級成員返回的指針。 (也將size_t更改為int因為它只是一個指針。)就像您在評論中建議的那樣,我添加了一個最小的可重現示例:

#include <iostream>

using namespace std;
//########## class without ~ destructor ##########
class classname
{
public:
    int *ptr;
    int *classfunction(int);
    void delete_classfunction(int*);
};


void classname::delete_classfunction(int*ptr)
{
    delete[] ptr;
    ptr = nullptr;
}

int *classname :: classfunction(int value)
{
    int* ptr = new int[value]; //no delete?
    ptr[0] = 5;
    return ptr;
}
//########## class with ~destructor ##########
class classname_c
{
public:
    int *ptr;
    int value;

    *classname_c(int );
    void print(int*);
    ~classname_c();

};

void classname_c::print(int* ptr)
{
    cout << ptr[0] << " shows value" << endl;
}

*classname_c::classname_c(int value)
{
    int* ptr = new int[value];
    ptr[0] = value;
} /*Brings warning: control reaches end of non-void function [-Wreturn-type]
   48 | }
      | ^*/


classname_c::~classname_c ()
{
    cout << ptr[0] << endl;
    delete[] ptr;
    ptr = nullptr;
    cout << ptr[0] << endl;
}

int main()
{   //class and deleting it myself calling the function delte
    int value = 3;
    int *ptr;
    classname call;
    ptr = call.classfunction(value); //create new ptr
    cout << ptr[0] << " shows value" << endl;
    call.delete_classfunction(ptr); //free memory
    cout << ptr[0] << " shows value succ. deleted" << endl;

    //class with destructor
    classname_c dest(value);
    dest.print(ptr);
    cout << ptr[0] << " shows value succ. deleted" << endl; //its not!


    return 0;
}

帶來以下輸出:

5 shows value
0 shows value succ. deleted //How it should be
3 shows value
3 shows value succ. deleted  //but its not, why? What did I do wrong?
Press <RETURN> to close this window...

現在我不確定 ~destructor 是否/何時工作,或者我如何測試我是否正確創建了析構函數,因為 ptr 值沒有被刪除。 我也可以修復

warning: control reaches end of non-void function [-Wreturn-type]
   48 | }
      | ^

從成員函數返回一個指針是完全沒問題的,盡管返回一個指向分配的size_t的指針似乎有點矯枉過正。

你想要的可能是這樣的:

#include <iostream>

class cls
{
public:
    size_t *ptr_func();
};

size_t *cls::ptr_func()
{
    size_t *p = new size_t(42);

    return p;
}

int main()
{
    cls c;
    size_t *p = c.ptr_func();

    std::cout << (void *)p << '\n';
    std::cout << *p;

    delete p;
}

這可能無法回答您的問題,但它可能會說明為什么這不符合您的預期。 當您調用類的成員函數時,即classname::function() ,您需要有該類的實例來調用它。 已經定義的東西

class classname {
public:
    classname() {ptr = new int(0);}
    size_t* function();
    ~classname();

    int* ptr;
};

size_t* classname::classfunction() {
    size_t* ptr = new size_t();
    return ptr;
}

不能被調用

classname * p_p = classfunction();

因為classfunction()沒有在classname的實例上被調用,並且因為classname不是size_t所以你不能將classname分配給返回類型size_t的函數的返回值,除非已經明確定義了從一個到另一個的強制轉換(相同用於classname*size_t* )。 你可以做這樣的事情

classname cls;
size_t* ptr = cls.classfunction();

另請注意,析構函數不用於成員函數,僅用於類,因此語法~size_t*class::function()沒有真正意義。

如果您試圖獲取指向類實例的指針,您可以簡單地執行

classname * ptr = new classname();

並把你的//... do something ...放在一個構造函數中。

編輯

析構函數的用途是執行

[...] 類在其生命周期結束時需要進行必要的清理。

這意味着當所述類的實例超出范圍或被手動刪除時,會調用析構函數。 所以當你有一個如上定義的類時,使用析構函數

classname::~classname() {
    delete ptr;
}

這意味着當classname的實例達到其“生命周期”的末尾時, ptr將被刪除。 例如

int main() {
   classname* cls = new classname();
   // cls->ptr == int(0)
   delete cls; // Calls ~classname()
   // cls->ptr == NULL
}

堆棧分配( classname cls(); )也是如此,無論哪種情況,析構函數都會在main的末尾自動調用(如果該實例尚未被手動刪除)。

現在不能做的是delete一個在類實例之外分配的指針 - 如果你希望能夠控制這樣的指針,同時仍然可以從類外部訪問它,你可以使它成為公共成員,就像我一樣在編輯過的類聲明中做了。 這允許您從類外部訪問指針,然后仍然使用析構函數刪除它,

int main() {
    classname* cls = new classname();
    // cls->ptr == 0
    cls->ptr = 3;
    // cls->ptr == 3
    delete cls;
    // cls->ptr == NULL
}

希望這提供了一些清晰度。


警告是因為構造函數

*classname_c::classname_c(int value) {//...}

....在你真正知道你在做什么之前不要這樣做,如果你想要一個指向類實例的指針,構造函數應該是

classname_c::classname_c(int value) {//...}

你應該用

classname_c* cls = new classname_c(value);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM