Berikut program singkatnya
#include <vector>
#include <iostream>
std::vector<int> someNums()
{
return {3, 5, 7, 11};
}
class Woop
{
public:
Woop(const std::vector<int>& nums) : numbers(nums) {}
void report()
{
for (int i : numbers)
std::cout << i << ' ';
std::cout << '\n';
}
private:
const std::vector<int>& numbers;
};
int main()
{
Woop woop(someNums());
woop.report();
}
memiliki masalah referensi yang menggantung, yang sepertinya tidak diperingatkan oleh kompiler. Masalahnya adalah bahwa temporaries dapat diikat ke const-ref, yang kemudian dapat Anda pertahankan. Pertanyaannya kemudian adalah; Apakah ada metode untuk menghindari masalah ini? Lebih disukai yang tidak melibatkan pengorbanan kebenaran konst, atau selalu membuat salinan benda-benda besar.
std::unique_ptr
untuk kepemilikan eksklusif, ataustd::shared_ptr
atau kepemilikan bersama, ataustd::weak_ptr
, setidaknya, mengenali data yang hilang).-fsanitize=address
. Saya tidak berpikir ada praktik terbaik untuk menghindarinya tanpa mengorbankan kinerja.Jawaban:
Dalam situasi ketika beberapa metode menyimpan referensi setelah kembali itu adalah ide yang baik untuk digunakan
std::reference_wrapper
daripada referensi normal:Woop (std::vector<int> const &&) = delete;
untuk metode Anda:sumber
Salah satu cara untuk membuat kelas Anda tidak terlalu rentan adalah dengan menambahkan konstruktor yang dihapus yang membutuhkan ref-kanan. Ini akan menghentikan instance kelas Anda dari membuat binding ke temporaries.
Konstruktor yang dihapus ini sebenarnya akan membuat kode O / P tidak dikompilasi, yang mungkin merupakan perilaku yang Anda cari?
sumber
Saya setuju dengan jawaban dan komentar lain yang harus Anda pikirkan dengan cermat jika Anda benar-benar perlu menyimpan referensi di dalam kelas. Dan jika Anda melakukannya, Anda mungkin ingin pointer non-const ke vektor const sebagai gantinya (yaitu
std::vector<int> const * numbers_
).Namun, jika itu masalahnya, saya menemukan bahwa jawaban lain yang saat ini diposting tidak penting. Semuanya menunjukkan kepada Anda cara membuat
Woop
memiliki nilai-nilai itu.Jika Anda dapat memastikan bahwa vektor yang Anda masukkan akan bertahan lebih lama dari
Woop
instance Anda , maka Anda dapat secara eksplisit menonaktifkan membangunWoop
dari nilai. Itu mungkin menggunakan sintaks C ++ 11 ini:Sekarang kode contoh Anda tidak akan dikompilasi lagi. Kompiler dengan memberikan kesalahan mirip dengan:
PS: Anda mungkin menginginkan konstruktor eksplisit, lihat mis. Apa arti kata kunci eksplisit? .
sumber
Untuk mencegah kasus tertentu, Anda dapat memilih untuk mengambil pointer (karena
Weep(&std::vector<int>{1,2,3})
tidak diizinkan) atau Anda dapat mengambil referensi non-const yang juga akan kesalahan sementara.Ini masih tidak menjamin nilainya tetap valid, tetapi paling tidak menghentikan kesalahan yang paling mudah, tidak membuat salinan, dan tidak perlu
nums
dibuat dengan cara khusus (misalnya sepertistd::shared_ptr
ataustd::weak_ptr
tidak).std::scoped_lock
mengambil referensi ke mutex akan menjadi contoh, dan satu di mana ptr unik / bersama / lemah tidak benar-benar diinginkan. Seringkalistd::mutex
hanya akan menjadi anggota dasar atau variabel lokal. Anda masih harus sangat berhati-hati, tetapi dalam kasus ini umumnya mudah untuk menentukan rentang hidup.std::weak_ptr
adalah pilihan lain untuk tidak memiliki, tetapi kemudian Anda memaksa pemanggil untuk menggunakanshared_ptr
(dan dengan demikian juga menumpuk mengalokasikan), dan kadang-kadang itu tidak diinginkan.Jika salinannya OK, itu hanya menghindari masalah.
Jika
Woop
harus mengambil kepemilikan, lewati sebagai nilai-r dan pindahkan (dan hindari sama sekali masalah penunjuk / referensi), atau gunakanunique_ptr
jika Anda tidak dapat memindahkan nilainya sendiri atau ingin penunjuk tetap valid.Atau jika kepemilikan dibagi, Anda dapat menggunakan
shared_ptr
untuk semuanya, dan itu akan dihapus bersama dengan referensi terakhir, tetapi ini dapat membuat melacak siklus hidup objek menjadi sangat membingungkan jika digunakan berlebihan.sumber
Anda dapat menggunakan
template programming
danarrays
jika Anda ingin memiliki objek yang menampungconst
wadah. Karenaconstexpr
konstruktor danconstexpr arrays
Anda mencapaiconst correctness
dancompile time execution
.Berikut adalah posting yang mungkin menarik: std :: move a const vector
jalankan kode
Keluaran:
sumber
std::array
ini dijamin untuk disalin, bahkan jika langkah lain akan tersedia. Di atas semua ituwooping1
danwooping2
bukan tipe yang sama, yang kurang dari ideal.