Con trỏ thông minh là gì và khi nào tôi nên sử dụng một con trỏ thông minh?

1885
Alex Reynolds 2008-09-20 14:09.

Con trỏ thông minh là gì và khi nào tôi nên sử dụng một con trỏ thông minh?

14 answers

1930
Lloyd 2008-09-20 14:48.

CẬP NHẬT

Câu trả lời này khá cũ và do đó mô tả những gì là 'tốt' vào thời điểm đó, đó là các con trỏ thông minh được cung cấp bởi thư viện Boost. Kể từ C ++ 11, các thư viện chuẩn đã được cung cấp đủ con trỏ thông minh loại, và vì vậy bạn nên ủng hộ việc sử dụng std::unique_ptr, std::shared_ptrstd::weak_ptr.

Cũng có std::auto_ptr. Nó rất giống một con trỏ trong phạm vi, ngoại trừ việc nó còn có khả năng sao chép nguy hiểm "đặc biệt" - điều này cũng bất ngờ chuyển quyền sở hữu.
Nó không được chấp nhận trong C ++ 11 và bị loại bỏ trong C ++ 17 , vì vậy bạn không nên sử dụng nó.

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

CÂU TRẢ LỜI CŨ

Con trỏ thông minh là một lớp bao bọc một con trỏ C ++ 'thô' (hoặc 'trần'), để quản lý thời gian tồn tại của đối tượng được trỏ tới. Không có một loại con trỏ thông minh nào, nhưng tất cả chúng đều cố gắng trừu tượng hóa một con trỏ thô theo cách thực tế.

Con trỏ thông minh nên được ưu tiên hơn con trỏ thô. Nếu bạn cảm thấy cần sử dụng con trỏ (trước tiên hãy cân nhắc nếu bạn thực sự muốn), thông thường bạn sẽ muốn sử dụng con trỏ thông minh vì điều này có thể giảm bớt nhiều vấn đề với con trỏ thô, chủ yếu là quên xóa đối tượng và rò rỉ bộ nhớ.

Với con trỏ thô, lập trình viên phải hủy đối tượng một cách rõ ràng khi nó không còn hữu ích nữa.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?

Một con trỏ thông minh bằng cách so sánh xác định một chính sách về thời điểm đối tượng bị phá hủy. Bạn vẫn phải tạo đối tượng, nhưng bạn không còn phải lo lắng về việc phá hủy nó.

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

Chính sách đơn giản nhất đang được sử dụng liên quan đến phạm vi của đối tượng trình bao bọc con trỏ thông minh, chẳng hạn như được triển khai bởi boost::scoped_ptrhoặc std::unique_ptr.

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

Lưu ý rằng std::unique_ptrkhông thể sao chép các phiên bản. Điều này ngăn con trỏ bị xóa nhiều lần (không chính xác). Tuy nhiên, bạn có thể chuyển các tham chiếu đến nó đến các hàm khác mà bạn gọi.

std::unique_ptrs hữu ích khi bạn muốn gắn thời gian tồn tại của đối tượng với một khối mã cụ thể hoặc nếu bạn nhúng nó dưới dạng dữ liệu thành viên bên trong một đối tượng khác, thì thời gian tồn tại của đối tượng khác đó. Đối tượng tồn tại cho đến khi khối mã chứa được thoát ra, hoặc cho đến khi đối tượng chứa chính nó bị phá hủy.

Chính sách con trỏ thông minh phức tạp hơn liên quan đến việc đếm tham chiếu con trỏ. Điều này cho phép con trỏ được sao chép. Khi "tham chiếu" cuối cùng đến đối tượng bị hủy, đối tượng sẽ bị xóa. Chính sách này được thực hiện bởi boost::shared_ptrstd::shared_ptr.

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

Con trỏ được đếm tham chiếu rất hữu ích khi vòng đời của đối tượng của bạn phức tạp hơn nhiều và không bị ràng buộc trực tiếp với một phần mã cụ thể hoặc với một đối tượng khác.

Có một nhược điểm đối với các con trỏ được đếm tham chiếu - khả năng tạo ra một tham chiếu lơ lửng:

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

Một khả năng khác là tạo các tham chiếu vòng tròn:

struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

Để giải quyết vấn đề này, cả Boost và C ++ 11 đều đã định nghĩa a weak_ptrđể xác định một tham chiếu yếu (chưa được đếm) cho a shared_ptr.

327
einpoklum 2015-05-10 09:06.

Đây là một câu trả lời đơn giản cho những ngày này của C ++ hiện đại (C ++ 11 trở lên):

  • "Con trỏ thông minh là gì?"
    Đó là một loại có các giá trị có thể được sử dụng như con trỏ, nhưng cung cấp thêm tính năng quản lý bộ nhớ tự động: Khi con trỏ thông minh không còn được sử dụng, bộ nhớ mà nó trỏ tới sẽ được phân bổ (xem thêm định nghĩa chi tiết hơn trên Wikipedia ).
  • "Khi nào tôi nên sử dụng một cái?"
    Trong mã liên quan đến việc theo dõi quyền sở hữu một phần bộ nhớ, cấp phát hoặc hủy cấp phát; con trỏ thông minh thường giúp bạn không cần phải làm những việc này một cách rõ ràng.
  • "Nhưng tôi nên sử dụng con trỏ thông minh nào trong những trường hợp đó?"
    • Sử dụng std::unique_ptrkhi bạn muốn đối tượng của mình tồn tại miễn là một tham chiếu sở hữu duy nhất đối với nó vẫn tồn tại. Ví dụ, sử dụng nó cho một con trỏ tới bộ nhớ được cấp phát khi nhập phạm vi nào đó và được cấp phát khi thoát khỏi phạm vi.
    • Sử dụng std::shared_ptrkhi bạn muốn tham chiếu đến đối tượng của mình từ nhiều nơi - và không muốn đối tượng của bạn bị hủy phân bổ cho đến khi tất cả các tham chiếu này tự biến mất.
    • Sử dụng std::weak_ptrkhi bạn muốn tham chiếu đến đối tượng của mình từ nhiều nơi - đối với những tham chiếu mà bạn có thể bỏ qua và phân bổ (vì vậy chúng sẽ chỉ ghi nhận đối tượng đã biến mất khi bạn cố gắng tham khảo).
    • Không sử dụng boost::con trỏ thông minh hoặc std::auto_ptrtrừ những trường hợp đặc biệt mà bạn có thể đọc lên nếu phải.
  • "Này, ta không hỏi dùng cái nào!"
    À, nhưng bạn thực sự muốn, hãy thừa nhận điều đó.
  • "Vậy khi nào tôi nên sử dụng con trỏ thông thường?"
    Chủ yếu là trong mã mà không biết đến quyền sở hữu bộ nhớ. Điều này thường xảy ra trong các hàm lấy một con trỏ từ một nơi khác và không cấp phát cũng như không cấp phát và không lưu trữ bản sao của con trỏ tồn tại lâu hơn việc thực thi của chúng.
114
sergtk 2008-09-20 14:32.

Con trỏ thông minh là loại giống con trỏ với một số chức năng bổ sung, ví dụ như định vị bộ nhớ tự động, đếm tham chiếu, v.v.

Một phần giới thiệu nhỏ có sẵn trên trang Con trỏ thông minh - Cái gì, Tại sao, Cái nào? .

Một trong những kiểu con trỏ thông minh đơn giản là std::auto_ptr(chương 20.4.5 của tiêu chuẩn C ++), cho phép người ta tự động phân bổ bộ nhớ khi nó nằm ngoài phạm vi và mạnh mẽ hơn cách sử dụng con trỏ đơn giản khi các ngoại lệ được ném ra, mặc dù kém linh hoạt hơn.

Một kiểu tiện lợi khác là boost::shared_ptrthực hiện đếm tham chiếu và tự động phân bổ bộ nhớ khi không còn tham chiếu đến đối tượng. Điều này giúp tránh rò rỉ bộ nhớ và dễ sử dụng để thực hiện RAII .

Chủ đề này được trình bày sâu trong cuốn sách "C ++ Templates: The Complete Guide" của David Vandevoorde, Nicolai M. Josuttis , chương Chương 20. Smart Pointers. Một số chủ đề được đề cập:

  • Bảo vệ chống lại các trường hợp ngoại lệ
  • Chủ sở hữu, (lưu ý, std :: auto_ptr đang triển khai loại con trỏ thông minh)
  • Thu thập tài nguyên là khởi tạo (Điều này thường được sử dụng để quản lý tài nguyên an toàn ngoại lệ trong C ++)
  • Giới hạn của chủ sở hữu
  • Đếm tham chiếu
  • Truy cập Bộ đếm Đồng thời
  • Tiêu hủy và Phân bổ
44
Sridhar Iyer 2008-09-20 15:53.

Các định nghĩa do Chris, Sergdev và Llyod cung cấp đều đúng. Tuy nhiên, tôi thích một định nghĩa đơn giản hơn, chỉ để giữ cho cuộc sống của tôi đơn giản: Con trỏ thông minh chỉ đơn giản là một lớp nạp chồng toán tử ->and *. Điều đó có nghĩa là đối tượng của bạn về mặt ngữ nghĩa trông giống như một con trỏ nhưng bạn có thể làm cho nó thực hiện những điều thú vị hơn, bao gồm đếm tham chiếu, hủy tự động, v.v. shared_ptrauto_ptrlà đủ trong hầu hết các trường hợp, nhưng đi kèm với tập hợp các đặc điểm riêng của chúng.

32
markets 2008-09-20 14:13.

Một con trỏ thông minh giống như một con trỏ thông thường (đã nhập), giống như "char *", ngoại trừ khi chính con trỏ đi ra khỏi phạm vi thì những gì nó trỏ đến cũng bị xóa. Bạn có thể sử dụng nó giống như một con trỏ thông thường, bằng cách sử dụng "->", nhưng không phải nếu bạn cần một con trỏ thực sự đến dữ liệu. Đối với điều đó, bạn có thể sử dụng "& * ptr".

Nó hữu ích cho:

  • Các đối tượng phải được cấp phát mới, nhưng bạn muốn có cùng thời gian tồn tại với một thứ gì đó trên ngăn xếp đó. Nếu đối tượng được gán cho một con trỏ thông minh, thì chúng sẽ bị xóa khi chương trình thoát khỏi chức năng / khối đó.

  • Thành viên dữ liệu của các lớp, do đó khi đối tượng bị xóa, tất cả dữ liệu sở hữu cũng bị xóa mà không có bất kỳ mã đặc biệt nào trong trình hủy (bạn sẽ cần đảm bảo trình hủy là ảo, điều này hầu như luôn luôn là điều nên làm) .

Bạn có thể không muốn sử dụng con trỏ thông minh khi:

  • ... con trỏ thực sự không nên sở hữu dữ liệu ... tức là khi bạn chỉ sử dụng dữ liệu, nhưng bạn muốn nó tồn tại trong chức năng mà bạn đang tham chiếu đến nó.
  • ... con trỏ thông minh không tự nó sẽ bị phá hủy vào một lúc nào đó. Bạn không muốn nó nằm trong bộ nhớ không bao giờ bị phá hủy (chẳng hạn như trong một đối tượng được cấp phát động nhưng sẽ không bị xóa rõ ràng).
  • ... hai con trỏ thông minh có thể trỏ đến cùng một dữ liệu. (Tuy nhiên, có những con trỏ thông minh hơn sẽ xử lý điều đó ... được gọi là đếm tham chiếu .)

Xem thêm:

  • thu gom rác thải .
  • Câu hỏi tràn ngăn xếp này liên quan đến quyền sở hữu dữ liệu
19
Chris Jester-Young 2008-09-20 14:14.

Hầu hết các loại con trỏ thông minh xử lý việc loại bỏ đối tượng con trỏ tới cho bạn. Nó rất tiện dụng vì bạn không phải suy nghĩ về việc loại bỏ các đối tượng theo cách thủ công nữa.

Các con trỏ thông minh được sử dụng phổ biến nhất là std::tr1::shared_ptr(hoặc boost::shared_ptr) và ít phổ biến hơn std::auto_ptr. Tôi khuyên bạn nên sử dụng thường xuyên shared_ptr.

shared_ptrrất linh hoạt và xử lý nhiều tình huống xử lý khác nhau, bao gồm cả các trường hợp mà các đối tượng cần được "vượt qua ranh giới DLL" (trường hợp ác mộng phổ biến nếu các mã khác nhau libcđược sử dụng giữa mã của bạn và các DLL).

19
Saqlain 2013-03-12 23:51.

Con trỏ thông minh là một đối tượng hoạt động giống như một con trỏ, nhưng cũng cung cấp thêm khả năng kiểm soát việc xây dựng, phá hủy, sao chép, di chuyển và tham khảo.

Người ta có thể triển khai con trỏ thông minh của riêng mình, nhưng nhiều thư viện cũng cung cấp các triển khai con trỏ thông minh, mỗi thư viện có những ưu điểm và nhược điểm khác nhau.

Ví dụ: Boost cung cấp các triển khai con trỏ thông minh sau:

  • shared_ptr<T>là một con trỏ để Tsử dụng số lượng tham chiếu để xác định khi nào đối tượng không còn cần thiết nữa.
  • scoped_ptr<T>là một con trỏ tự động bị xóa khi nó vượt ra khỏi phạm vi. Không thể phân công.
  • intrusive_ptr<T>là một con trỏ đếm tham chiếu khác. Nó cung cấp hiệu suất tốt hơn shared_ptr, nhưng yêu cầu loại Tphải cung cấp cơ chế đếm tham chiếu của riêng nó.
  • weak_ptr<T>là một con trỏ yếu, làm việc kết hợp với shared_ptrđể tránh các tham chiếu vòng tròn.
  • shared_array<T>giống như shared_ptr, nhưng đối với các mảng T.
  • scoped_array<T>giống như scoped_ptr, nhưng đối với các mảng T.

Đây chỉ là một mô tả tuyến tính của mỗi loại và có thể được sử dụng theo nhu cầu, để biết thêm chi tiết và các ví dụ, người ta có thể xem tài liệu của Boost.

Ngoài ra, thư viện tiêu chuẩn C ++ cung cấp ba con trỏ thông minh; std::unique_ptrcho quyền sở hữu duy nhất, std::shared_ptrcho quyền sở hữu chung và std::weak_ptr. std::auto_ptrtồn tại trong C ++ 03 nhưng hiện không được dùng nữa.

12
Santosh 2014-03-07 23:03.

Đây là Liên kết cho các câu trả lời tương tự: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

Con trỏ thông minh là một đối tượng hoạt động, trông giống như một con trỏ bình thường nhưng cung cấp nhiều chức năng hơn. Trong C ++, con trỏ thông minh được triển khai dưới dạng các lớp mẫu đóng gói một con trỏ và ghi đè các toán tử con trỏ tiêu chuẩn. Chúng có một số lợi thế so với con trỏ thông thường. Chúng được đảm bảo được khởi tạo dưới dạng con trỏ null hoặc con trỏ tới một đối tượng heap. Chuyển hướng thông qua một con trỏ null được kiểm tra. Không cần xóa. Các đối tượng tự động được giải phóng khi con trỏ cuối cùng đến chúng biến mất. Một vấn đề quan trọng với các con trỏ thông minh này là không giống như các con trỏ thông thường, chúng không tôn trọng tính kế thừa. Con trỏ thông minh không hấp dẫn đối với mã đa hình. Dưới đây là một ví dụ cho việc triển khai con trỏ thông minh.

Thí dụ:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

Lớp này triển khai một con trỏ thông minh tới một đối tượng kiểu X. Bản thân đối tượng này nằm trên heap. Đây là cách sử dụng nó:

smart_pointer <employee> p= employee("Harris",1333);

Giống như các toán tử được nạp chồng khác, p sẽ hoạt động giống như một con trỏ thông thường,

cout<<*p;
p->raise_salary(0.5);
10
Jorge Ferreira 2008-09-20 14:12.

http://en.wikipedia.org/wiki/Smart_pointer

Trong khoa học máy tính, con trỏ thông minh là một kiểu dữ liệu trừu tượng mô phỏng một con trỏ đồng thời cung cấp các tính năng bổ sung, chẳng hạn như thu gom rác tự động hoặc kiểm tra giới hạn. Các tính năng bổ sung này nhằm giảm thiểu các lỗi do sử dụng sai con trỏ trong khi vẫn giữ được hiệu quả. Con trỏ thông minh thường theo dõi các đối tượng trỏ đến chúng nhằm mục đích quản lý bộ nhớ. Việc lạm dụng con trỏ là một nguyên nhân chính gây ra lỗi: việc cấp phát, phân bổ và tham chiếu liên tục phải được thực hiện bởi một chương trình được viết bằng con trỏ làm cho rất có thể xảy ra một số rò rỉ bộ nhớ. Con trỏ thông minh cố gắng ngăn chặn rò rỉ bộ nhớ bằng cách làm cho việc phân bổ tài nguyên tự động: khi con trỏ tới một đối tượng (hoặc con trỏ cuối cùng trong một loạt các con trỏ) bị phá hủy, chẳng hạn như vì nó đi ra ngoài phạm vi, đối tượng được trỏ cũng bị hủy.

7
nnrales 2016-03-03 14:58.

Đặt T là một lớp trong hướng dẫn này Con trỏ trong C ++ có thể được chia thành 3 loại:

1) Con trỏ thô :

T a;  
T * _ptr = &a; 

Chúng giữ một địa chỉ bộ nhớ đến một vị trí trong bộ nhớ. Sử dụng một cách thận trọng, vì các chương trình trở nên phức tạp khó theo dõi.

Con trỏ có dữ liệu hoặc địa chỉ const {Đọc ngược}

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

Con trỏ tới một kiểu dữ liệu T là một hằng số. Có nghĩa là bạn không thể thay đổi kiểu dữ liệu bằng cách sử dụng con trỏ. tức là *ptr1 = 19; sẽ không làm việc. Nhưng bạn có thể di chuyển con trỏ. tức là ptr1++ , ptr1--; vv sẽ hoạt động. Đọc ngược: con trỏ đến kiểu T là const

  T * const ptr2 ;

Một con trỏ const tới một kiểu dữ liệu T. Có nghĩa là bạn không thể di chuyển con trỏ nhưng bạn có thể thay đổi giá trị được con trỏ trỏ tới. tức là *ptr2 = 19sẽ hoạt động nhưng ptr2++ ; ptr2--vv sẽ không hoạt động. Đọc ngược: con trỏ const đến một kiểu T

const T * const ptr3 ; 

Một con trỏ const tới một kiểu dữ liệu const T. Có nghĩa là bạn không thể di chuyển con trỏ cũng như không thể thay đổi con trỏ kiểu dữ liệu thành con trỏ. I E . ptr3-- ; ptr3++ ; *ptr3 = 19;sẽ không làm việc

3) Con trỏ thông minh : { #include <memory>}

Con trỏ chia sẻ :

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

Được triển khai bằng cách sử dụng đếm tham chiếu để theo dõi có bao nhiêu "thứ" trỏ đến đối tượng được con trỏ trỏ tới. Khi số lượng này về 0, đối tượng sẽ tự động bị xóa, tức là đối tượng bị xóa khi tất cả share_ptr trỏ đến đối tượng đi ra khỏi phạm vi. Điều này giúp loại bỏ sự đau đầu của việc phải xóa các đối tượng mà bạn đã cấp phát bằng cách sử dụng mới.

Con trỏ yếu: Giúp xử lý tham chiếu theo chu kỳ phát sinh khi sử dụng Con trỏ dùng chung Nếu bạn có hai đối tượng được trỏ tới bởi hai con trỏ dùng chung và có một con trỏ dùng chung nội bộ trỏ đến con trỏ được chia sẻ khác thì sẽ có một tham chiếu theo chu kỳ và đối tượng sẽ không bị xóa khi con trỏ được chia sẻ vượt ra ngoài phạm vi. Để giải quyết vấn đề này, hãy thay đổi thành viên nội bộ từ shared_ptr thành yếu_ptr. Lưu ý: Để truy cập phần tử được trỏ tới bởi một con trỏ yếu, hãy sử dụng lock (), điều này trả về giá trị yếu_ptr.

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

Hãy xem: Khi nào thì std :: thin_ptr hữu ích?

Con trỏ độc đáo: Con trỏ thông minh có trọng lượng nhẹ với quyền sở hữu độc quyền. Sử dụng khi con trỏ trỏ đến các đối tượng duy nhất mà không chia sẻ các đối tượng giữa các con trỏ.

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

Để thay đổi đối tượng được trỏ tới bởi ptr duy nhất, hãy sử dụng ngữ nghĩa di chuyển

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

Tham khảo: Về cơ bản, chúng có thể giống như con trỏ const, tức là một con trỏ là const và không thể di chuyển bằng cú pháp tốt hơn.

Hãy xem: Sự khác biệt giữa biến con trỏ và biến tham chiếu trong C ++ là gì?

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

Tài liệu tham khảo : https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ Cảm ơn Andre đã chỉ ra câu hỏi này.

4
Trombe 2017-06-13 13:23.

Con trỏ thông minh là một lớp, một lớp bao bọc của một con trỏ bình thường. Không giống như các con trỏ thông thường, vòng đời của điểm thông minh dựa trên số lượng tham chiếu (thời gian đối tượng con trỏ thông minh được gán). Vì vậy, bất cứ khi nào một con trỏ thông minh được gán cho một con trỏ khác, số tham chiếu bên trong sẽ cộng với cộng. Và bất cứ khi nào đối tượng đi ra ngoài phạm vi, số tham chiếu sẽ trừ đi.

Con trỏ tự động, mặc dù trông giống nhau, hoàn toàn khác với con trỏ thông minh. Nó là một lớp thuận tiện giúp phân bổ tài nguyên bất cứ khi nào một đối tượng con trỏ tự động đi ra khỏi phạm vi biến. Ở một mức độ nào đó, nó làm cho một con trỏ (tới bộ nhớ được cấp phát động) hoạt động tương tự như một biến ngăn xếp (được cấp phát tĩnh trong thời gian biên dịch).

2
Daksh 2016-11-07 18:07.

Con trỏ thông minh là những nơi bạn không phải lo lắng về việc phân bổ bộ nhớ, chia sẻ và truyền tài nguyên.

Bạn rất có thể sử dụng con trỏ này theo cách tương tự như bất kỳ phân bổ nào hoạt động trong Java. Trong java Garbage Collector thực hiện thủ thuật, trong khi trong Smart Pointers, thủ thuật được thực hiện bởi Destructors.

2
da77a 2018-01-26 17:10.

Các câu trả lời hiện có là tốt nhưng không bao gồm những việc phải làm khi con trỏ thông minh không phải là câu trả lời (đầy đủ) cho vấn đề bạn đang cố gắng giải quyết.

Trong số những thứ khác (được giải thích rõ trong các câu trả lời khác) sử dụng con trỏ thông minh là một giải pháp khả thi Làm cách nào để chúng ta sử dụng một lớp trừu tượng làm kiểu trả về của hàm? đã được đánh dấu là bản sao của câu hỏi này. Tuy nhiên, câu hỏi đầu tiên cần đặt ra nếu bị cám dỗ chỉ định một lớp cơ sở trừu tượng (hoặc trên thực tế là bất kỳ) làm kiểu trả về trong C ++ là "ý bạn thực sự là gì?". Có một cuộc thảo luận tốt (với các tài liệu tham khảo thêm) về lập trình hướng đối tượng thành ngữ trong C ++ (và điều này khác với các ngôn ngữ khác như thế nào) trong tài liệu của thư viện vùng chứa con trỏ tăng cường . Tóm lại, trong C ++ bạn phải nghĩ về quyền sở hữu. Con trỏ thông minh nào giúp bạn, nhưng không phải là giải pháp duy nhất hoặc luôn luôn là giải pháp hoàn chỉnh (chúng không cung cấp cho bạn bản sao đa hình) và không phải lúc nào cũng là giải pháp bạn muốn hiển thị trong giao diện của mình (và hàm trả về nghe có vẻ khủng khiếp rất giống một giao diện). Ví dụ, nó có thể đủ để trả về một tham chiếu. Nhưng trong tất cả các trường hợp này (con trỏ thông minh, vùng chứa con trỏ hoặc chỉ đơn giản là trả về một tham chiếu), bạn đã thay đổi trả về từ một giá trị thành một số dạng tham chiếu . Nếu bạn thực sự cần sao chép, bạn có thể cần thêm nhiều "thành ngữ" viết sẵn hơn hoặc vượt ra khỏi OOP thành ngữ (hoặc cách khác) trong C ++ sang tính đa hình chung hơn bằng cách sử dụng các thư viện như Adobe Poly hoặc Boost.TypeErasure .

1
lbsweek 2020-08-10 00:04.

Con trỏ thông minh là gì.

Phiên bản dài, Về nguyên tắc:

https://web.stanford.edu/class/archive/cs/cs106l/cs106l.1192/lectures/lecture15/15_RAII.pdf

Một thành ngữ C ++ hiện đại:

RAII: Resource Acquisition Is Initialization.

● When you initialize an object, it should already have 
  acquired any resources it needs (in the constructor).


● When an object goes out of scope, it should release every 
  resource it is using (using the destructor).

điểm quan trọng:

● There should never be a half-ready or half-dead object.
● When an object is created, it should be in a ready state.
● When an object goes out of scope, it should release its resources. 
● The user shouldn’t have to do anything more. 

Con trỏ thô vi phạm RAII : Nó cần người dùng xóa theo cách thủ công khi con trỏ đi ra khỏi phạm vi.

Giải pháp RAII là:

Have a smart pointer class:
● Allocates the memory when initialized
● Frees the memory when destructor is called
● Allows access to underlying pointer

Đối với con trỏ thông minh cần sao chép và chia sẻ, hãy sử dụng shared_ptr:

● use another memory to store Reference counting and shared.
● increment when copy, decrement when destructor.
● delete memory when Reference counting is 0. 
  also delete memory that store Reference counting.

đối với con trỏ thông minh không sở hữu con trỏ thô, hãy sử dụng yếu_ptr:

● not change Reference counting.

cách sử dụng shared_ptr:

correct way:
std::shared_ptr<T> t1 = std::make_shared<T>(TArgs);
std::shared_ptr<T> t2 = std::shared_ptr<T>(new T(Targs));

wrong way:
T* pt = new T(TArgs); // never exposure the raw pointer
shared_ptr<T> t1 = shared_ptr<T>(pt);
shared_ptr<T> t2 = shared_ptr<T>(pt);

Luôn tránh sử dụng con trỏ thô.

Đối với kịch bản phải sử dụng con trỏ thô:

https://stackoverflow.com/a/19432062/2482283

Đối với con trỏ thô không phải nullptr, hãy sử dụng tham chiếu thay thế.

not use T*
use T&  

Đối với tham chiếu tùy chọn có thể là nullptr, hãy sử dụng con trỏ thô và có nghĩa là:

T* pt; is optional reference and maybe nullptr.
Not own the raw pointer, 
Raw pointer is managed by some one else.
I only know that the caller is sure it is not released now.

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Trong Saturday Night Live, The Bachelor is Bland và Tina Fey trở lại với vai 'Crazy' Sarah Palin

Sau khi Sarah Palin tán thành Donald Trump vào đầu tuần này, gần như không thể tránh khỏi việc Tina Fey sẽ trở lại Saturday Night Live để thăm lại ấn tượng Palin cổ điển của cô. Và Fey chắc chắn đã không làm thất vọng, cô ấy đã đưa ra một lời khen ngợi không hề nhẹ về bài phát biểu chứng thực Iowa quanh co và khó hiểu của Palin trong khi Trump của Darrell Hammond đưa ra bình luận xuyên suốt.

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Đây có phải là sự khởi đầu cho sự kết thúc của việc giam giữ Brittney Griner?

Brittney Griner (r.) Ngay từ đầu, thân phận của Brittney Griner đã là tình huống con tin Mỹ độc nhất trong lịch sử hiện đại.

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Tom Brady là bộ tứ vệ đầu tiên cuối cùng có thể giúp Julio Jones có hơn 10 lần chạm bóng trong một mùa giải

Chúng ta có thể thấy nhiều hơn nữa về một Julio Jones khỏe mạnh trong khu vực cuối năm nay. John Parker Wilson, Greg McElroy, A.

Đó phải là Đức

Đó phải là Đức

Đối với đội tuyển Anh, không có kẻ thủ ác nào lớn hơn Hầu hết các cổ động viên Anh, nếu không muốn nói là tất cả, hẳn sẽ phải gật gù khi tiếng còi mãn cuộc của trận bán kết lượt về W Euro 2022 vang lên. Bởi vì nó báo hiệu rằng Đức sẽ chờ đợi ở Wembley trong trận chung kết với Anh và là điều duy nhất giữa Anh và chiếc cúp lớn đầu tiên của đội tuyển nữ.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Language