Saya kira tidak, tapi saya ingin mengonfirmasi. Apakah ada gunanya const Foo&&
, dimana Foo
tipe kelasnya?
c++
c++11
constants
rvalue-reference
fredoverflow
sumber
sumber
const&&
sangat penting, meskipun dia tidak mengatakan alasannya: youtube.com/watch?v=JhgWFYfdIho#t=54m20sJawaban:
Mereka terkadang berguna. Draf C ++ 0x sendiri menggunakannya di beberapa tempat, misalnya:
template <class T> void ref(const T&&) = delete; template <class T> void cref(const T&&) = delete;
Dua kelebihan beban di atas memastikan bahwa fungsi
ref(T&)
dan lainnyacref(const T&)
tidak terikat ke nilai r (yang jika tidak dimungkinkan).Memperbarui
Saya baru saja memeriksa standar resmi N3290 , yang sayangnya tidak tersedia untuk umum, dan ada di 20.8 Objek fungsi [function.objects] / p2:
template <class T> void ref(const T&&) = delete; template <class T> void cref(const T&&) = delete;
Kemudian saya memeriksa draf post-C ++ 11 terbaru, yang tersedia untuk umum, N3485 , dan di 20,8 Objek fungsi [function.objects] / p2 masih mengatakan:
template <class T> void ref(const T&&) = delete; template <class T> void cref(const T&&) = delete;
sumber
const T&&
yang digunakan?const T&&
mencegah seseorang dengan bodohnya menggunakan template eksplisit args dari formulirref<const A&>(...)
. Itu bukan argumen yang sangat kuat, tetapi biayaconst T&&
lebihT&&
cukup minim.Semantik mendapatkan referensi nilai konstanta (dan bukan untuk
=delete
) adalah untuk mengatakan:Kasus penggunaan berikut bisa jadi IMHO kasus penggunaan yang baik untuk referensi nilai r ke const , meskipun bahasa memutuskan untuk tidak menggunakan pendekatan ini (lihat posting SO asli ).
Kasus: konstruktor pointer pintar dari pointer mentah
Biasanya disarankan untuk menggunakan
make_unique
danmake_shared
, tetapi keduanyaunique_ptr
danshared_ptr
dapat dibuat dari penunjuk mentah. Kedua konstruktor mendapatkan pointer berdasarkan nilai dan menyalinnya. Keduanya memungkinkan (yaitu dalam arti: tidak mencegah ) penggunaan lanjutan dari penunjuk asli yang diteruskan kepada mereka di konstruktor.Kode berikut mengkompilasi dan hasil dengan gratis ganda :
int* ptr = new int(9); std::unique_ptr<int> p { ptr }; // we forgot that ptr is already being managed delete ptr;
Keduanya
unique_ptr
danshared_ptr
dapat mencegah hal di atas jika konstruktor relevan mereka mengharapkan untuk mendapatkan pointer mentah sebagai nilai konstanta , misalnya untukunique_ptr
:unique_ptr(T* const&& p) : ptr{p} {}
Dalam hal ini kode bebas ganda di atas tidak akan dikompilasi, tetapi yang berikut akan:
std::unique_ptr<int> p1 { std::move(ptr) }; // more verbose: user moves ownership std::unique_ptr<int> p2 { new int(7) }; // ok, rvalue
Catatan itu
ptr
masih bisa digunakan setelah dipindahkan, jadi potensi bug tidak hilang sama sekali. Tetapi jika pengguna diminta untuk memanggilstd::move
bug seperti itu akan jatuh ke dalam aturan umum: jangan gunakan sumber daya yang dipindahkan.Seseorang dapat bertanya: OK, tapi mengapa
T*
const&& p
?Alasannya sederhana, untuk memungkinkan pembuatan dari
unique_ptr
pointer const . Ingatlah bahwa referensi nilai r lebih umum daripada hanya referensi nilai r karena ia menerima keduanyaconst
dannon-const
. Jadi kami dapat mengizinkan yang berikut:int* const ptr = new int(9); auto p = std::unique_ptr<int> { std::move(ptr) };
ini tidak akan berjalan jika kita hanya mengharapkan rvalue reference (kesalahan kompilasi: tidak dapat mengikat const rvalue ke rvalue ).
Bagaimanapun, ini sudah terlambat untuk mengusulkan hal seperti itu. Tapi ide ini memang menyajikan penggunaan yang wajar dari rujukan nilai r ke const .
sumber
Mereka diperbolehkan dan bahkan fungsi diberi peringkat berdasarkan
const
, tetapi karena Anda tidak dapat berpindah dari objek const yang dirujukconst Foo&&
, mereka tidak berguna.sumber
const T&, T&, const T&&, T&&
Selain std :: ref , pustaka standar juga menggunakan referensi rvalue const di std :: as_const untuk tujuan yang sama.
template <class T> void as_const(const T&&) = delete;
Ini juga digunakan sebagai nilai kembalian di std :: opsional saat mendapatkan nilai yang dibungkus:
constexpr const T&& operator*() const&&; constexpr const T&& value() const &&;
Serta di std :: get :
template <class T, class... Types> constexpr const T&& get(const std::variant<Types...>&& v); template< class T, class... Types > constexpr const T&& get(const tuple<Types...>&& t) noexcept;
Ini mungkin untuk menjaga kategori nilai serta keteguhan pembungkus saat mengakses nilai yang dibungkus.
Ini membuat perbedaan apakah fungsi yang memenuhi syarat nilai rvalue const dapat dipanggil pada objek yang dibungkus. Yang mengatakan, saya tidak tahu kegunaan apa pun untuk fungsi yang memenuhi syarat nilai rvalue const.
sumber
Saya tidak dapat memikirkan situasi di mana ini akan berguna secara langsung, tetapi ini mungkin digunakan secara tidak langsung:
template<class T> void f(T const &x) { cout << "lvalue"; } template<class T> void f(T &&x) { cout << "rvalue"; } template<class T> void g(T &x) { f(T()); } template<class T> void h(T const &x) { g(x); }
T dalam g adalah T konst, jadi f 's x adalah T konst &&.
Kemungkinan ini menghasilkan kesalahan comile di f (ketika mencoba untuk memindahkan atau menggunakan objek), tetapi f bisa mengambil rvalue-ref sehingga tidak bisa dipanggil pada lvalues, tanpa memodifikasi rvalue (seperti pada terlalu sederhana contoh di atas).
sumber