Apa yang harus diberikan pada fungsi yang mengharapkan pointer mentah?

Saya menggunakan perpustakaan yang, untuk membuat beberapa objek yang saya gunakan, mengharapkan pointer mentah ke suatu objek. Saya tidak yakin apa yang akan dilakukannya dengan penunjuk, untuk membuat kode saya seaman mungkin, apa yang harus saya teruskan ke fungsi ini?

  1. Gunakan penunjuk unik - jika mereka memutuskan untuk menghapus penunjuk, saya akan melakukan penghapusan ganda
  2. Melacak penunjuk mentah - buruk karena saya harus ingat untuk menulis hapus, tetapi masih bisa berupa penghapusan ganda
  3. Gunakan durasi otomatis dan beri mereka petunjuk Beri mereka referensi - kode mereka akan error jika mereka memanggil delete
  4. Gunakan penunjuk bersama - masalah penghapusan ganda yang sama dengan penunjuk unik, tetapi sekarang cakupan saya tidak akan merusak penunjuknya

Berdasarkan bacaan saya, opsi 3 sepertinya yang harus saya lakukan - mereka tidak boleh memanggil delete pada pointer, dan format ini menerapkannya. Tetapi bagaimana jika saya tidak tahu apakah mereka sekarang atau di masa depan akan menghapus referensi yang saya berikan kepada mereka? Gunakan penunjuk bersama dan katakan bukan salah saya tentang penghapusan ganda?

#include <memory>
#include <iostream>

class ComplexObj {
  public:
    ComplexObj() : m_field(0) {}
    ComplexObj(int data) : m_field(data) {}

    void print() { std::cout << m_field << std::endl; }

  private:
    int m_field;
};

class BlackBox {
  public:
    BlackBox(ComplexObj* data) {
        m_field = *data;

        // Do other things I guess...

        delete data;
        std::cout << "Construction complete" << std::endl;
    }

    void print_data() { m_field.print(); }

  private:
    ComplexObj m_field;
};

int main(int argc, char* argv[]) {
    // Use a smart pointer
    std::unique_ptr<ComplexObj> my_ptr(new ComplexObj(1));
    BlackBox obj1 = BlackBox(my_ptr.get());
    obj1.print_data();
    my_ptr->print();  // Bad data, since BlackBox free'd
    // double delete when my_ptr goes out of scope

    // Manually manage the memory
    ComplexObj* manual = new ComplexObj(2);
    BlackBox obj2 = BlackBox(manual);
    obj2.print_data();
    manual->print();  // Bad data, since BlackBox free'd
    delete manual;    // Pair new and delete, but this is a double delete

    // Edit: use auto-duration and give them a pointer
    ComplexObj by_ref(3);
    BlackBox obj3 = BlackBox(&by_ref);  // they can't call delete on the pointer they have
    obj3.print_data();
    by_ref.print();

    // Use a shared pointer
    std::shared_ptr<ComplexObj> our_ptr(new ComplexObj(4));
    BlackBox obj4 = BlackBox(our_ptr.get());
    obj4.print_data();
    our_ptr->print();  // Bad data, they have free'd
    // double delete when our_ptr goes out of scope

    return 0;
}

Pertanyaan lain yang saya baca terkait dengan topik ini...


person Jay    schedule 08.01.2021    source sumber
comment
Mengapa menebak? Baca manual perpustakaan untuk mengetahui apakah itu akan menghapus penunjuk atau tidak.   -  person HolyBlackCat    schedule 08.01.2021
comment
Beri mereka referensi - kode mereka akan error jika mereka memanggil delete - Tidak yakin apa yang Anda maksud di sini, jika fungsi mengharapkan pointer, Anda tidak dapat memberikan referensi. Di BlackBox obj3 = BlackBox(&by_ref); &ref bukan referensi, melainkan mengambil alamat ref.   -  person churill    schedule 08.01.2021
comment
Baca dokumentasi mereka. Jika mereka mengatakan bahwa mereka mengambil kepemilikan atas penunjuk tersebut, maka Anda tahu bahwa Anda tidak perlu menghapusnya. Jika mereka tidak mengatakan apa-apa, secara umum anggaplah Anda perlu membersihkannya. Jika mereka tidak mendokumentasikan barang-barang mereka dengan benar sehingga menyebabkan kebocoran memori atau penghapusan ganda, maka komplainlah dengan keras.   -  person TheUndeadFish    schedule 08.01.2021


Jawaban (1)


Anda tidak dapat menyelesaikan masalah ini dengan informasi yang Anda miliki. Semua pilihan menghasilkan sampah.

Anda harus membaca dokumentasi API yang Anda gunakan.

Melakukan salah satu dari 4 jawaban Anda tanpa mengetahui apakah jawaban tersebut mengambil alih kepemilikan penunjuk akan menimbulkan masalah.

Hidup terkadang menyebalkan.

Jika Anda memiliki API yang rusak atau tidak bersahabat, satu-satunya hal yang aman untuk dilakukan adalah berinteraksi dengannya dalam proses terpisah, dengan hati-hati menghapus semua komunikasi, dan mematikan proses.

Jika API tidak rusak atau tidak bersahabat, Anda seharusnya dapat mengetahui apakah API tersebut mengambil alih kepemilikan objek yang ditunjuk. Memanggil API tanpa menyadarinya adalah kesalahan umum yang dilakukan programmer C++ pemula. Jangan lakukan itu. Ya, ini menyebalkan.

Jika API ini bersifat internal dan Anda memiliki kendali apa pun, usahakan agar semua argumen penunjuk kepemilikan menjadi std::unique_ptr<>s. Hal ini memperjelas di API bahwa Anda bermaksud memiliki objek tersebut dan menghapusnya nanti.

person Yakk - Adam Nevraumont    schedule 08.01.2021