3

i try to learn how to use smart pointers. I use for the long time normal pointers and i think i need some upgrade of my skills.

I make some research, i understand some aspects of smart pointers, but i try to implement in a clear project to see how smart pointers work. I try:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; }
};

int main()
{
    std::shared_ptr<int>f1(new int[100]);

    f1.get()[1] = 1;
    std::cout << f1.get()[1];
}

all good, message it's print. But when i try:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; };
};

int main()
{
    std::shared_ptr<Entity>f1(new Entity[100]);

    f1.get()[1].print();
}

I get this error: [img]https://i.stack.imgur.com/hMDIZ.png

next:

int main()
{
    std::shared_ptr<Entity>f1(new Entity[100]);

    (f1.get() + 1)->print();
}

same error.

I try to use std::make_shared:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; };
};

int main()
{
    std::shared_ptr<Entity>f1 = std::make_shared<Entity>();

    f1->print();
}

everything it's ok.

I try to alocate continue memory with int:

#include <iostream>
#include <array>
#include <memory>

class Entity
{
public:
    Entity()
    {
        std::cout << "Entity called!" << std::endl;
    }
    ~Entity()
    {
        std::cout << "Entity destroyed!" << std::endl;
    }
    void print() { std::cout << "Message!"; };
};

int main()
{
    std::shared_ptr<int>f1 = std::make_shared<int>(100);

    f1.get()[1] = 10;
    std::cout << f1.get()[1];
}

message it's printed, output: 10 but error: https://i.imgur.com/UPu7VZo.png

i try in another way:

int main()
{
    std::shared_ptr<int>f1 = std::make_shared<int>(100);

    *(f1.get() +1) = 10;
    std::cout << *(f1.get() + 1);
}

same error.

std::shared_ptr<Entity[]>f1 = std::make_shared<Entity[]>(new Entity[100]);

i have error...

What i try to make something like this:

int main()
{
    Entity* f1 = new Entity[100];

    f1[0].print();
    f1[1].print();
    f1[2].print();

}

but i want to use smart pointers.

for int i want to make some assigned value like this:

int main()
{
    int* f1 = new int[100];

    f1[0] = 14;
    f1[1] = 20;
    f1[2] = 5;
}

How can i make something like this with smart pointers. I want to use: std::make_shared(new Entity[100]) or something like this.

I can try with library like vector or array but i don't want to use this library for the moment. I want to keep my code clear for the moment. After i understand 100% smart pointers i will use array and vector library

  • 1
    Error messages are text. Paste the text here; don't link to an image of text. – tenfour Mar 30 '20 at 11:54
  • 1
    You should use `std::shared_ptr` or the container will try to call `delete` instead of `delete[]` which is wrong https://stackoverflow.com/questions/1553382/is-delete-equal-to-delete – Cory Kramer Mar 30 '20 at 11:57
  • Does this answer your question? [shared\_ptr to an array : should it be used?](https://stackoverflow.com/questions/13061979/shared-ptr-to-an-array-should-it-be-used) – a1ezh Mar 30 '20 at 12:01
  • `make_shared` creates ("makes") a shared object. It does not take a pointer to an object and "make it shared". – molbdnilo Mar 30 '20 at 12:02
  • 1
    While `std::shared_ptr` is possible, `std::vector` and `std::array` are more common. Smart pointers are only one of the replacements of dumb pointers. The standard containers are another replacement. – MSalters Mar 30 '20 at 12:02
  • any reason why you wouldn't use `unique_ptr`? – Waqar Mar 30 '20 at 12:28

2 Answers2

5

Not

std::shared_ptr<Entity[]> f1 = std::make_shared<Entity[]>(new Entity[100]);

but

std::shared_ptr<Entity[]> f1 = std::make_shared<Entity[]>(100);

or even simpler

auto f1 = std::make_shared<Entity[]>(100);

When you use make_shared you should not use new. One of the points of make_shared is to allocate memory more efficiently that it would be if you used new.

Note: the array form of make_shared requires C++20.

john
  • 85,011
  • 4
  • 57
  • 81
2

The code sample that should work for you is:

int main() {
    std::shared_ptr<Entity[]>f1(new Entity[100]);

    f1.get()[1].print();
}

As for make_shared, you're out of luck - the current CPP standard, 17, doesn't seem to support it (see https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared) However, make_shared is only used to eliminate a race condition in allocation and can be implemented manually or just omitted. I encourage reading more about it.

NadavS
  • 779
  • 3
  • 12
  • your code work.. but i don't understand exacly: auto sp = std::make_shared(12); static_assert(std::is_same_v>); std::cout << sp->i << '\n'; in my case C++17: auto f2 = std::make_shared(100); //compile without errors how can i acces f2.get()[1].printf()? i need to make static_assert? – Claudiu Andries Mar 30 '20 at 12:31
  • and question 2: how can i take care about race condition in allocation, how can i implement manual? – Claudiu Andries Mar 30 '20 at 12:35
  • I don't understand question 1. – NadavS Mar 30 '20 at 12:41
  • In question 2, the issue is that if the constructor of `shared_ptr` fails you leak your allocation. AFAIK, the code to solve it is: – NadavS Mar 30 '20 at 12:44
  • shared_ptr p; T* temp_ptr = new T(); try { p = temp_ptr; } catch(...) { delete temp_ptr; throw; } – NadavS Mar 30 '20 at 12:45
  • question 1: i see an exemple on cppreference : auto sp = std::make_shared(12); how can i get the acces on sp[1] sp[2]? – Claudiu Andries Mar 30 '20 at 12:47
  • in this example, if I understand correcty, there is only one `C`, not an array of `C` s. Therefore, it is not what you're looking fore. – NadavS Mar 30 '20 at 12:49