Apakah legal untuk mengalokasikan pointer baru?

33

Pointer ke fungsi bukan pointer data biasa karena tidak dapat disimpan dalam pointer * kosong. Meskipun demikian, tampaknya saya dapat menyimpan salinan fungsi-pointer dalam memori dinamis (dalam gcc dan dentang) seperti pada kode di bawah ini. Apakah kode tersebut legal menurut Standar C ++, atau mungkin ini semacam ekstensi kompiler?

Selain itu, pointer yang dihasilkan ke function-pointer berperilaku sebagai pointer data biasa: Saya dapat menyimpannya di void * dan mengambilnya dari void * oleh static_cast. Apakah perilaku ini dijamin oleh Standar?

int main()
{
  extern void fcn();
  void (*fcnPtr)() = &fcn;
  void (**ptrToFcnPtr)() = nullptr;

  //Make the copy of fcnPtr on the heap:
  ptrToFcnPtr = new decltype(fcnPtr)(fcnPtr);
  //Call the pointed-to function : 
  (**ptrToFcnPtr)();

  //Save the pointer in void* :
  void *ptr = ptrToFcnPtr;
  //retrieve the original ptr: 
  auto myPtr = static_cast< void(**)() > (ptr) ; 
  //free memory:
  delete ptrToFcnPtr ;

}
Adrian
sumber
2
Tolong jangan gunakan pointer fungsi mentah. Gunakan std::functionsebagai gantinya.
Beberapa programmer Bung
Anda tidak perlu newdilemparkan void*. void* ptr = &fcnPtr;berfungsi dengan baik, karena fcnPtrmerupakan objek, bukan fungsi.
walnut
5
@Someprogrammerdude std::functionadalah wadah tipe-terhapus untuk menyimpan callable sewenang-wenang, bukan pengganti pengganti fungsi pointer ...
Michael Kenzel
7
(@Someprogrammerdude) Tolong jangan gunakan / merekomendasikan secara membabi buta std::function. Ini bagus untuk kemampuannya menyimpan fungsi "polimorfik" (yaitu apa saja dengan tanda tangan yang benar, bahkan jika itu berisi keadaan seperti dalam kasus beberapa lambda), tetapi itu juga menambahkan overhead yang mungkin tidak diperlukan. Pointer ke fungsi adalah POD. A std::functionbukan.
Matius
2
@ Matius Agar adil, Adrian bertanya tentang secara dinamis mengalokasikan pointer untuk berfungsi dan menunjuk ke sana dengan tipe-hapus void*, jadi dalam konteks pertanyaan ini std::functiontampaknya persis apa yang mereka cari. Saya setuju bahwa pemecatan umum pointer fungsi SPD tidak sehat.
eerorika

Jawaban:

27

Sementara pointer fungsi bukan pointer objek, "pointer ke fungsi beberapa tipe" masih merupakan tipe objek [basic.types] / 8 . Dengan demikian, fungsi pointer adalah objek itu sendiri, hanya hal yang mereka tuju bukan.

Dengan demikian, Anda yakin dapat membuat objek tipe pointer fungsi melalui ekspresi baru ...

Michael Kenzel
sumber
9

karena mereka (fungsi pointer) tidak dapat disimpan dalam pointer * kosong.

Sebenarnya, menyimpan pointer fungsi sebagai void*kondisional didukung. Ini berarti bahwa dapat atau tidak dapat disimpan tergantung pada implementasi bahasa. Jika implementasi bahasa mendukung pemuatan dinamis, maka konversi penunjuk fungsi di void*mungkin didukung. GCC, Dentang dan MSVC semua mendukung ini:

reinterpret_cast<void*>(&function);

Apakah legal untuk mengalokasikan pointer baru?

Tentu. Semua pointer, termasuk pointer fungsi, adalah objek dan semua objek dapat dialokasikan secara dinamis.

Selain itu, pointer yang dihasilkan ke function-pointer berperilaku sebagai pointer data biasa

Pointer fungsi adalah sebuah objek. Pointer ke pointer fungsi tidak hanya "berperilaku", tetapi adalah pointer ke objek.

Saya dapat menyimpannya di void * dan mengambilnya dari void * dengan static_cast. Apakah perilaku ini dijamin oleh Standar?

Konversi antara pointer ke void dan pointer ke objek diperbolehkan, ya. Dan konversi pulang pergi dijamin untuk menghasilkan pointer asli.

eerorika
sumber
Terima kasih. Tetapi kemudian untuk mengubah fungsi-pointer ke void * (atau sebaliknya) saya perlu menggunakan reinterpret_cast, kan?
Adrian
1
@Adrian Ya. Saya menambahkan contoh.
eerorika
Jika ada yang ingin pengecualian mungkin: dos model memori menengah + overlay. Pointer fungsi lebih besar daripada pointer data dalam model sedang, dan overlay dapat digunakan untuk mencapai plugin jika Anda berusaha cukup keras.
Joshua