Perbedaan antara `const shared_ptr <T>` dan `shared_ptr <const T>`?

115

Saya menulis metode pengakses untuk penunjuk bersama di C ++ yang berjalan seperti ini:

class Foo {
public:
    return_type getBar() const {
        return m_bar;
    }

private:
    boost::shared_ptr<Bar> m_bar;
}

Jadi untuk mendukung keteguhan getBar()jenis kembalian haruslah boost::shared_ptryang mencegah modifikasi dari Barpoin itu. Dugaan saya adalah shared_ptr<const Bar>tipe yang ingin saya kembalikan untuk melakukan itu, sedangkan const shared_ptr<Bar>akan mencegah penugasan ulang pointer itu sendiri untuk menunjuk ke yang berbeda Bartetapi memungkinkan modifikasi dari Baryang ditunjukkannya ... Namun, saya tidak yakin. Saya akan menghargai jika seseorang yang tahu pasti bisa mengkonfirmasi ini, atau mengoreksi saya jika saya salah. Terima kasih!

Dave Lillethun
sumber
3
Persis seperti yang Anda katakan. Anda dapat melihat dokumentasi untuk operator *dan ->untuk memastikannya.
syam
2
Apa perbedaan antara T *constdan T const *? Sama.
3
@ H2CO3 Tidak sama sekali. The constbiasanya memodifikasi apa _precedes, jadi T *constadalah constpointer ke T, dan T const*adalah pointer ke const T. Dan yang terbaik adalah menghindari penggunaan consttanpa apa pun sebelumnya.
James Kanze
6
@JamesKanze, itulah poin H2CO3: perbedaan antara T *constdan T const *sama dengan perbedaan antara const shared_ptr<T>danshared_ptr<const T>
Jonathan Wakely
1
@ JamesKanze Oh tapi ya. T *constadalah pointer const ke non-const T, begitu juga const shared_ptr<T>. Sebaliknya, T const *adalah penunjuk non-const ke const T, begitu juga shared_ptr<const T>.

Jawaban:

176

Kamu benar. shared_ptr<const T> p;mirip dengan const T * p;(atau, sama, T const * p;), yaitu menunjuk objek adalah constsedangkan const shared_ptr<T> p;mirip dengan T* const p;yang artinya padalah const. Singkatnya:

shared_ptr<T> p;             ---> T * p;                                    : nothing is const
const shared_ptr<T> p;       ---> T * const p;                              : p is const
shared_ptr<const T> p;       ---> const T * p;       <=> T const * p;       : *p is const
const shared_ptr<const T> p; ---> const T * const p; <=> T const * const p; : p and *p are const.

Hal yang sama berlaku untuk weak_ptrdan unique_ptr.

Cassio Neri
sumber
1
Anda juga menjawab pertanyaan yang saya miliki di belakang kepala saya tentang pointer biasa (const T * vs. T * const vs. T const *). :) Saya tidak menyebutkannya karena saya tidak ingin pertanyaan saya tentang SO menjadi terlalu luas, dan ini adalah pertanyaan yang berkaitan dengan tugas saya saat ini. Bagaimanapun, saya pikir saya mengerti dengan sangat baik sekarang. Terima kasih!
Dave Lillethun
9
Saya senang ini membantu. Tip terakhir yang saya gunakan untuk mengingat tentang const T* p;', 'T const * p;dan T * const p. Lihat *sebagai pemisah dalam arti apa constyang ada di sisi yang sama *.
Cassio Neri
5
Aturan praktis saya adalah constselalu mengacu pada hal yang ada di sisi kirinya. Jika tidak ada yang ada di kiri, itu adalah benda di sisi kanan.
hochl
hochi — bagaimana dengan const T * p; setara dengan T const * p ;?
Vlad
Cassio, Anda dapat menambahkan bahwa dalam kasus tipe yang dikembalikan const shared_ptr <T>, ini tidak dapat digunakan dalam fungsi non-const sementara ini tidak berlaku untuk pointer const.
Vlad
2

boost::shared_ptr<Bar const>mencegah modifikasi Barobjek melalui penunjuk bersama. Sebagai nilai yang dikembalikan, const in boost::shared_ptr<Bar> constberarti Anda tidak dapat memanggil fungsi non-const pada fungsi sementara yang dikembalikan; jika itu untuk penunjuk nyata (misalnya Bar* const), itu akan sepenuhnya diabaikan.

Secara umum, bahkan di sini, aturan yang biasa berlaku: constmemodifikasi apa yang mendahuluinya: in boost::shared_ptr<Bar const>, the Bar; di boost::shared_ptr<Bar> const, itu adalah instantiation (ekspresi boost::shared_ptr<Bar>yang const.

James Kanze
sumber
1
@gatopeich Jadi Anda bisa delete.
Marcin
@ARCIN, bisakah kamu menjelaskannya?
gatopeich
1
#Check this simple code to understand... copy-paste the below code to check on any c++11 compiler

#include <memory>
using namespace std;

class A {
    public:
        int a = 5;
};

shared_ptr<A> f1() {
    const shared_ptr<A> sA(new A);
    shared_ptr<A> sA2(new A);
    sA = sA2; // compile-error
    return sA;
}

shared_ptr<A> f2() {
    shared_ptr<const A> sA(new A);
    sA->a = 4; // compile-error
    return sA;
}

int main(int argc, char** argv) {
    f1();
    f2();
    return 0;
}
vivek2k6
sumber
Izinkan saya menyarankan penggunaan std::make_shared()(sejak C ++ 14).
Joel Bodenmann
0

Saya ingin demo sederhana berdasarkan jawaban @Cassio Neri:

#include <memory>

int main(){
    std::shared_ptr<int> i = std::make_shared<int>(1);
    std::shared_ptr<int const> ci;

    // i = ci; // compile error
    ci = i;
    std::cout << *i << "\t" << *ci << std::endl; // both will be 1

    *i = 2;
    std::cout << *i << "\t" << *ci << std::endl; // both will be 2

    i = std::make_shared<int>(3);
    std::cout << *i << "\t" << *ci << std::endl; // only *i has changed

    // *ci = 20; // compile error
    ci = std::make_shared<int>(5);
    std::cout << *i << "\t" << *ci << std::endl; // only *ci has changed

}
Jónás Balázs
sumber