After the appearance of new features in C ++ such as std::make_shared() and std::make_unique , the question arises: Is there at least one case when you really need to work with a raw pointer?

In this question, I do not take into account the cases when a third-party library takes a pointer in any of the methods.

I am taking a middle level programmer in C ++. He writes his library without using third-party code. And I have no examples when he really needs to use raw pointers.

  • You can refer to the first field structure of type int through a raw pointer like this: * (int *) struct_ptr, and then crawl out of misunderstanding C ++ monkeys - typemoon
  • I doubt that the average programmer should write his libraries on the crosses. - avp

5 answers 5

In the internal details of the implementation, when owning pointers complicate the interaction, when it is necessary to divide ownership, but the lifetime of the object is clearly determined and there is no question: where and when to clean an object ( shared_ptr in such cases is superfluous), when the link is not enough, because the situation is possible with nullptr on the object. In public APIs, try to avoid as long as possible, or clearly substantiate - "why?" and for what?".

In general, I adhere to the rule: do without raw pointers, as long as it is possible. Not yet let down (embedded).

By the way, it is probably funny, but in C projects, upon reaching a certain level of complexity, shared ownership mechanisms also begin to appear. These are the well-known xxx_ref(object) / xxx_unref(object) . Examples: GLib with its gobject, FFmpeg actively implements reference counting for AVPacket and AVFrame ( intrusive_ptr exists in Boost for such cases), the Linux kernel also does not stand aside ( https://lwn.net/Articles/336224/ according to the word Reference Counting or http://www.makelinux.net/books/lkd2/ch17lev1sec7 ) with your kobject .

    The most commonplace example is wood. Each node stores a parent. You can, of course, store in weak_ptr , but this is not convenient and, in my opinion, stupid. Therefore, in this case a “naked” pointer is used. You can come up with other examples, but their essence will be as follows: “bare” pointers, in modern code, can and should be used when we do not own what we refer to and we have confidence that what we refer to is not "Die" before us.


    There is a great video from Straustrup on this topic: Writing Good C ++ 14 . The lion’s share is dedicated to pointers.

    • Why weak_ptr ? There is not shared ownership. - Abyx pm
    • @Abyx, you can make the node a successor of enable_shared_from_this and store all descendants in shared_ptr , but how to store a parent is already a choice - either “naked” or weak_ptr - ixSci

    The said smart pointers are proprietary. Those. when the smart pointer's destructor is called, the data is either immediately released ( std::unique_ptr ), or the ownership counter ( std::shared_ptr ) is reduced, and when zero is reached, the data is released.

    If the pointer does not own the data, it makes sense to use raw pointers. The minor exception is std::weak_ptr - a non-possessing pointer, but derived from std::shared_ptr .

    Most likely, it is necessary to use raw pointers when interacting with old (up to C++11 ) code or even C code. For example, working with char* strings.

    • What is smart pointers I know. The question is different: What if there is no need to use third-party code and legacy code, then what can force a programmer to use raw pointers? Nothing. So? - sys_dev
    • four
      @sys_dev no. Not this way. For example, if you want to use dynamic_cast it will return a raw pointer (well, or a link). When working with arrays, pointers may be required. The main thing to keep in mind is that a raw pointer is maximum performance. Smart pointers, in most cases, are overhead. - αλεχολυτ
    • I always believed that if a person needed to use dynamic_cast , then he thought badly about how to solve his problem - sys_dev
    • 3
      @sys_dev in most cases, this is probably true. But software is usually not created entirely from scratch, but uses ready-made (not only standard) libraries and frameworks, in which there may be functions (handlers with a fixed signature) that take a pointer to the base class. And in this handler you have to (have to) make a dynamic_cast , since the derived class adds new features that were simply not in the base. - αλεχολυτ
    • @alexolut, dynamic_pointer_cast - ixSci

    Want the simplest example? :)

     int main(int , char**) 

    You can do without a lot, just there are situations where this detour is much longer than a straight road.

      The same std::shared_ptr<T> takes twice as much memory (because of the pointer to the counter). For structures (trees, for example) actively using pointers, this can be a significant addition. And passing them by value is copying onto the stack twice as much data. Yes, in large projects it is often not so noticeable that this is memory consumption, but there are also exceptional situations.

      • There is no counter in the shared_ptr<T> object. But there is a direct pointer to the object, so it takes two pointers. - Abyx 2:07 pm
      • Wrong, pointer to the counter, of course - int3