ความแตกต่างระหว่าง `const shared_ptr <T>` และ `shared_ptr <const T>`?


116

ฉันกำลังเขียนวิธีการเข้าถึงสำหรับตัวชี้ที่ใช้ร่วมกันใน C ++ ซึ่งมีลักษณะดังนี้:

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

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

ดังนั้นเพื่อรองรับ const-ness ของgetBar()ประเภทการส่งคืนควรเป็นสิ่งboost::shared_ptrที่ป้องกันการแก้ไขที่Barชี้ไป ฉันเดาว่าshared_ptr<const Bar>เป็นประเภทที่ฉันต้องการกลับไปทำเช่นนั้นในขณะที่const shared_ptr<Bar>จะป้องกันไม่ให้การกำหนดตัวชี้ซ้ำเพื่อชี้ไปยังตำแหน่งอื่นBarแต่อนุญาตให้แก้ไขสิ่งBarที่ชี้ไป ... อย่างไรก็ตามฉันไม่แน่ใจ ฉันจะขอบคุณมากถ้ามีคนที่รู้แน่ชัดสามารถยืนยันเรื่องนี้หรือแก้ไขฉันได้หากฉันเข้าใจผิด ขอบคุณ!


3
ก็ตรงตามที่คุณบอก คุณสามารถดูเอกสารสำหรับตัวดำเนินการ*และ->เพื่อยืนยันสิ่งนี้
syam

2
อะไรคือความแตกต่างระหว่างT *constและT const *? เหมือน.

3
@ H2CO3 ไม่เลย. constปกติปรับเปลี่ยนสิ่งที่ _precedes จึงT *constเป็นconstตัวชี้ไปTและเป็นตัวชี้ไปT const* const Tและที่ดีที่สุดคือหลีกเลี่ยงการใช้โดยconstไม่มีอะไรมาก่อน
James Kanze

6
@JamesKanze นั่นคือจุดของ H2CO3: ความแตกต่างระหว่างT *constและT const *เหมือนกับความแตกต่างระหว่าง const shared_ptr<T>และshared_ptr<const T>
Jonathan Wakely

1
@JamesKanze โอ้ แต่ใช่ T *constเป็นตัวชี้ const ไม่ใช่ const ก็เป็นอย่างนั้นT const shared_ptr<T>ในทางตรงกันข้ามT const *เป็นตัวชี้ไม่ใช่ const ไปก็เป็นอย่างนั้นconst T shared_ptr<const T>

คำตอบ:


176

คุณพูดถูก shared_ptr<const T> p;คล้ายกับconst T * p;(หรือเท่ากันT const * p;) นั่นคือวัตถุปลายแหลมอยู่ในconstขณะที่const shared_ptr<T> p;มีความคล้ายคลึงกับT* const p;ซึ่งหมายความว่าเป็นp constสรุป:

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.

เดียวกันถือสำหรับและweak_ptrunique_ptr


1
คุณยังตอบคำถามที่ฉันมีในด้านหลังศีรษะเกี่ยวกับพอยน์เตอร์ปกติ (const T * เทียบกับ T * const เทียบกับ T const *) :) ฉันไม่ได้พูดถึงเรื่องนั้นเพราะฉันไม่ต้องการให้คำถามของฉันเกี่ยวกับ SO กว้างเกินไปและนี่คือคำถามที่เกี่ยวข้องกับงานปัจจุบันของฉัน อย่างไรก็ตามตอนนี้ฉันคิดว่าฉันเข้าใจดีแล้ว ขอบคุณ!
Dave Lillethun

9
ฉันดีใจที่ช่วยได้ เคล็ดลับสุดท้ายที่ผมใช้ในการจำเกี่ยวกับและconst T* p;', 'T const * p; T * const pดู*เป็นตัวคั่นในแง่ที่ว่าอะไรconstคือสิ่งที่อยู่ด้านเดียวกันของ*.
Cassio Neri

5
หลักการทั่วไปของฉันคือconstมักจะหมายถึงสิ่งที่อยู่ทางด้านซ้ายของมัน ถ้าไม่มีอะไรอยู่ทางซ้ายแสดงว่าอยู่ทางด้านขวา
hochl

hochi - แล้ว const T * p; เทียบเท่ากับ T const * p;?
Vlad

Cassio คุณสามารถเพิ่มได้ในกรณีของประเภทที่ส่งคืน const shared_ptr <T> จะไม่สามารถใช้ในฟังก์ชันที่ไม่ใช่ const ได้ในขณะที่สิ่งนี้ไม่เป็นจริงสำหรับตัวชี้ const
Vlad

2

boost::shared_ptr<Bar const>ป้องกันการแก้ไข Barวัตถุผ่านตัวชี้ที่ใช้ร่วมกัน ในฐานะที่เป็นค่าส่งคืนค่า const boost::shared_ptr<Bar> constหมายความว่าคุณไม่สามารถเรียกใช้ฟังก์ชันที่ไม่ใช่ const บนฟังก์ชันที่ส่งคืนชั่วคราว หากเป็นตัวชี้จริง (เช่นBar* const) มันจะถูกละเว้นโดยสิ้นเชิง

โดยทั่วไปถึงแม้ที่นี่กฎปกติใช้: constปรับเปลี่ยนสิ่งที่นำหน้ามันในboost::shared_ptr<Bar const>ที่Bar; ในboost::shared_ptr<Bar> constมันคืออินสแตนซ์ (นิพจน์boost::shared_ptr<Bar>ซึ่งเป็น const.


1
@gatopeich เพื่อให้คุณได้deleteมัน
Marcin

@ Marcin คุณสามารถอธิบายได้หรือไม่?
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;
}

ฉันขอแนะนำการใช้งานstd::make_shared()(ตั้งแต่ C ++ 14)
Joel Bodenmann

0

ฉันต้องการการสาธิตอย่างง่ายตามคำตอบของ @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

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.