Kode berikut tidak dikompilasi.
int a = 1, b = 2, c = 3;
int& arr[] = {a,b,c,8};
Apa yang dikatakan standar C ++ tentang ini?
Saya tahu saya bisa mendeklarasikan kelas yang berisi referensi, lalu membuat array kelas itu, seperti yang ditunjukkan di bawah ini. Tetapi saya benar-benar ingin tahu mengapa kode di atas tidak dapat dikompilasi.
struct cintref
{
cintref(const int & ref) : ref(ref) {}
operator const int &() { return ref; }
private:
const int & ref;
void operator=(const cintref &);
};
int main()
{
int a=1,b=2,c=3;
//typedef const int & cintref;
cintref arr[] = {a,b,c,8};
}
Dimungkinkan untuk menggunakan struct cintref
alih-alih const int &
mensimulasikan array referensi.
intlink value = 8;
tidak bekerja. periksa apakah Anda tidak percaya.operator=
. Referensi tidak dapat diulang. Jika Anda benar-benar ingin semantik seperti - meskipun saya tidak secara pribadi menemukan situasi di mana mereka praktis berguna - makastd::reference_wrapper
akan menjadi cara untuk melakukannya, karena sebenarnya menyimpan pointer tetapi menyediakan referensi-sepertioperator
dan tidak memungkinkan reseating. Tapi kemudian saya hanya menggunakan pointer!Jawaban:
Menjawab pertanyaan Anda tentang standar saya dapat mengutip C ++ Standar §8.3.2 / 4 :
sumber
struct
satu-satunya yang menjadi referensi. Tapi kemudian, dengan melakukannya, Anda sekarang punya referensi & objek induk untuk nama ... yang sekarang berarti Anda dapat dengan jelas menyatakan alamat mana yang Anda inginkan. Tampak jelas ... jadi mengapa tidak ada yang mengatakannya?What more is there to say?
Alasan mengapa ? Saya semua tentang Standar, tetapi hanya mengutipnya dan mengasumsikan bahwa akhir dari diskusi sepertinya adalah cara yang pasti untuk menghancurkan pemikiran kritis pengguna - bersama dengan potensi apa pun untuk bahasa berkembang, misalnya di luar batasan kelalaian atau pembatasan buatan. Ada terlalu banyak 'karena Standar mengatakan' di sini - dan tidak cukup 'dan sangat masuk akal untuk mengatakan itu, karena alasan praktis berikut'. Saya tidak tahu mengapa upvotes mengalir dengan sangat bersemangat ke jawaban yang hanya mengatakan yang pertama tanpa mencoba untuk mengeksplorasi yang terakhir.Referensi bukan objek. Mereka tidak memiliki penyimpanan sendiri, mereka hanya mereferensikan objek yang ada. Untuk alasan ini, tidak masuk akal untuk memiliki array referensi.
Jika Anda ingin ringan objek yang referensi objek lain maka Anda dapat menggunakan pointer. Anda hanya akan dapat menggunakan a
struct
dengan anggota referensi sebagai objek dalam array jika Anda memberikan inisialisasi eksplisit untuk semua anggota referensi untuk semuastruct
instance. Referensi tidak dapat secara default diinisialisasi.Sunting: Seperti catatan jia3ep, di bagian standar tentang deklarasi ada larangan eksplisit pada array referensi.
sumber
Ini diskusi yang menarik. Array yang jelas jelas ilegal, tetapi IMHO alasan mengapa tidak sesederhana mengatakan 'mereka bukan benda' atau 'mereka tidak memiliki ukuran'. Saya akan menunjukkan bahwa array itu sendiri bukan objek yang lengkap dalam C / C ++ - jika Anda keberatan, coba instantiating beberapa kelas template stl menggunakan array sebagai parameter template 'class', dan lihat apa yang terjadi. Anda tidak dapat mengembalikannya, menetapkannya, meneruskannya sebagai parameter. (param array diperlakukan sebagai pointer). Tetapi adalah legal untuk membuat array dari array. Referensi memang memiliki ukuran yang dapat dan harus dihitung oleh kompilator - Anda tidak dapat sizeof () referensi, tetapi Anda dapat membuat struct yang hanya berisi referensi. Ini akan memiliki ukuran yang cukup untuk memuat semua pointer yang mengimplementasikan referensi. Kamu bisa'
Bahkan Anda dapat menambahkan baris ini ke definisi struct
... dan sekarang saya memiliki sesuatu yang terlihat BANYAK seperti serangkaian referensi:
Sekarang, ini bukan array nyata, ini kelebihan operator; itu tidak akan melakukan hal-hal yang biasanya dilakukan array seperti sizeof (arr) / sizeof (arr [0]), misalnya. Tapi itu tidak persis apa yang saya ingin array referensi lakukan, dengan C ++ legal. Kecuali (a) itu sulit untuk mengatur lebih dari 3 atau 4 elemen, dan (b) melakukan perhitungan menggunakan sekelompok? , tetapi tetap mengindeks). Saya ingin melihat tipe 'array referensi' yang sangat terbatas yang sebenarnya dapat melakukan ini. Yaitu array referensi tidak akan diperlakukan sebagai array umum dari hal-hal yang merupakan referensi, tetapi akan menjadi 'array-referensi-baru' buat dengan templat).
ini mungkin akan berhasil, jika Anda tidak keberatan dengan jenis jahat ini: menyusun kembali '* this' sebagai array int * dan mengembalikan referensi yang dibuat dari satu: (tidak disarankan, tetapi ini menunjukkan bagaimana 'array' yang tepat) akan bekerja):
sumber
std::tuple<int&,int&,int&> abcref = std::tie( a,b,c)
- yang menciptakan "array" referensi yang hanya dapat diindeks oleh konstanta kompilasi-waktu menggunakan std :: get. Tapi kamu tidak bisa melakukannyastd::array<int&,3> abcrefarr = std::tie( a,b,c)
. Mungkin ada cara untuk melakukannya yang tidak saya ketahui. Sepertinya saya harus ada cara untuk menulis spesialisasistd::array<T&,N>
yang dapat melakukan ini - dan dengan demikian fungsistd::tiearray(...)
yang mengembalikan satu seperti itu (atau memungkinkanstd::array<T&,N>
untuk menerima inisialisasi yang berisi alamat = {& v1, & v2 dll})?:
std::array<T,N>
, mudah didefinisikan dalam kode aplikasi, tidak ditambahkan ke std :: sampai c ++ 11, mungkin karena berkutat untuk memiliki ini tanpa cara untuk do= {1,2,3};
Apakah itu 'bahasa hacker'?Komentar untuk hasil edit Anda:
Solusi yang lebih baik adalah
std::reference_wrapper
.Detail: http://www.cplusplus.com/reference/functional/reference_wrapper/
Contoh:
sumber
reference_wrapper
.Array secara implisit dapat dikonversi menjadi pointer, dan pointer-to-reference ilegal di C ++
sumber
Diberikan
int& arr[] = {a,b,c,8};
, apa itusizeof(*arr)
?Di tempat lain, referensi diperlakukan hanya sebagai hal itu sendiri, jadi
sizeof(*arr)
seharusnya begitu sajasizeof(int)
. Tapi ini akan membuat array pointer aritmatika pada array ini salah (dengan asumsi referensi yang lebar tidak sama dengan int). Untuk menghilangkan ambiguitas, itu dilarang.sumber
struct
yang hanya memiliki referensi itu dan mencari tahu ..?Karena seperti yang banyak dikatakan di sini, referensi bukanlah objek. mereka hanyalah alias. Benar beberapa kompiler mungkin mengimplementasikannya sebagai pointer, tetapi standar tidak memaksa / menentukan itu. Dan karena referensi bukan objek, Anda tidak dapat mengarahkannya. Menyimpan elemen dalam array berarti ada beberapa jenis alamat indeks (yaitu, menunjuk ke elemen pada indeks tertentu); dan itulah sebabnya Anda tidak dapat memiliki array referensi, karena Anda tidak dapat mengarahkannya.
Gunakan boost :: reference_wrapper, atau boost :: tuple sebagai gantinya; atau hanya petunjuk.
sumber
Saya percaya jawabannya sangat sederhana dan ada hubungannya dengan aturan referensi semantik dan bagaimana array ditangani dalam C ++.
Singkatnya: Referensi dapat dianggap sebagai struct yang tidak memiliki konstruktor default, jadi semua aturan yang sama berlaku.
1) Secara semantik, referensi tidak memiliki nilai default. Referensi hanya dapat dibuat dengan merujuk sesuatu. Referensi tidak memiliki nilai untuk mewakili tidak adanya referensi.
2) Saat mengalokasikan array ukuran X, program membuat koleksi objek yang diinisialisasi default. Karena referensi tidak memiliki nilai default, membuat array seperti itu secara semantik ilegal.
Aturan ini juga berlaku untuk struct / kelas yang tidak memiliki konstruktor default. Contoh kode berikut tidak dikompilasi:
sumber
Object
, Anda hanya perlu memastikan untuk menginisialisasi mereka semua:Object objects[1] = {Object(42)};
. Sementara itu, Anda tidak dapat membuat array referensi, bahkan jika Anda menginisialisasi semuanya.Anda bisa cukup dekat dengan struct template ini. Namun, Anda perlu menginisialisasi dengan ekspresi yang mengarah ke T, bukan T; jadi, meskipun Anda dapat dengan mudah membuat 'fake_constref_array' dengan cara yang sama, Anda tidak akan dapat mengikatnya ke nilai seperti yang dilakukan dalam contoh OP ('8');
-> A = 0 B = 7 X = {0,8,0}
sumber
Objek referensi tidak memiliki ukuran. Jika Anda menulis
sizeof(referenceVariable)
, itu akan memberi Anda ukuran objek yang dirujukreferenceVariable
, bukan referensi itu sendiri. Ia tidak memiliki ukuran sendiri, itulah sebabnya kompiler tidak dapat menghitung berapa ukuran array yang diperlukan.sumber
Ketika Anda menyimpan sesuatu dalam sebuah array, ukurannya perlu diketahui (karena pengindeksan array bergantung pada ukurannya). Per standar C ++ Tidak ditentukan apakah referensi membutuhkan penyimpanan atau tidak, karena itu pengindeksan array referensi tidak mungkin dilakukan.
sumber
struct
, secara ajaib semuanya menjadi ditentukan, didefinisikan dengan baik, dijamin, dan ukuran deterministik. Karena itu, mengapa perbedaan yang tampaknya sepenuhnya buatan ini ada?struct
diberikan oleh pembungkus itu , beberapa jawaban yang baik mulai menunjukkan diri mereka sendiri - tetapi bagi saya, belum ada yang melakukannya, meskipun ini menjadi salah satu tantangan langsung bagi semua orang. alasan mengapa Anda tidak dapat menggunakan referensi yang tidak terbungkus.Hanya untuk menambah semua percakapan. Karena array memerlukan lokasi memori berturut-turut untuk menyimpan item, jadi jika kita membuat array referensi maka tidak dijamin bahwa mereka akan berada di lokasi memori berturut-turut sehingga mengakses akan menjadi masalah dan karenanya kita bahkan tidak dapat menerapkan semua operasi matematika pada Himpunan.
sumber
Pertimbangkan berbagai petunjuk. Pointer adalah alamat; jadi ketika Anda menginisialisasi array, Anda memberi tahu komputer secara analog, "alokasikan blok memori ini untuk menampung angka-angka X ini (yang merupakan alamat barang-barang lainnya)." Kemudian jika Anda mengubah salah satu dari pointer, Anda hanya mengubah apa yang ditunjukkannya; itu masih alamat numerik yang dengan sendirinya duduk di tempat yang sama.
Referensi analog dengan alias. Jika Anda mendeklarasikan serangkaian referensi, Anda pada dasarnya akan memberi tahu komputer, "alokasikan gumpalan memori amorf ini yang terdiri dari semua item berbeda yang tersebar di sekitarnya."
sumber
struct
-satunya anggotanya yang menjadi referensi menghasilkan sesuatu yang sepenuhnya legal, dapat diprediksi, dan tidak amorf? Mengapa pengguna harus membungkus referensi agar dapat secara ajaib mendapatkan kekuatan array, atau itu hanya pembatasan buatan? IMO tidak ada jawaban yang langsung membahas hal ini. Saya berasumsi bantahannya adalah 'Objek pembungkus memastikan Anda dapat menggunakan semantik nilai, dalam bentuk objek pembungkus, sehingga memastikan Anda dapat memiliki jaminan nilai, yang diperlukan karena misalnya bagaimana seseorang akan ambigu antara elemen dan alamat wasit' ... Apakah itu yang kamu maksud?Sebenarnya, ini adalah campuran dari sintaks C dan C ++.
Anda harus baik menggunakan array C murni, yang tidak dapat referensi, karena referensi merupakan bagian dari C ++ saja. Atau Anda menggunakan cara C ++ dan menggunakan kelas
std::vector
ataustd::array
untuk tujuan Anda.Adapun bagian yang diedit: Meskipun
struct
merupakan elemen dari C, Anda mendefinisikan fungsi konstruktor dan operator, yang membuatnya menjadi C ++class
. Akibatnya, Andastruct
tidak akan dikompilasi dalam C murni!sumber
std::vector
ataustd::array
tidak dapat memuat referensi. Standar C ++ cukup eksplisit sehingga tidak ada wadah yang bisa.