Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a vector of shared_ptr to ints

Attempting to create a vector of shared_ptr to int.

Where am I going wrong? Thanks. Keith :^)

#include <iostream>
#include <vector>
#include <memory>

int main() {
    std::vector<std::shared_ptr<int> > w;
    std::vector<std::shared_ptr<int> >::iterator it_w;
    w.push_back(new int(7));

    std::cout << std::endl;
}

Compiler result:

pickledegg> g++ -std=c++11 -o shared_ptr shared_ptr.cpp
shared_ptr.cpp:29:4: error: no matching member function for call to 'push_back'
        w.push_back(new int(7));
        ~~^~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:697:36: note: 
      candidate function not viable: no known conversion from 'int *' to 'const value_type' (aka
      'const std::__1::shared_ptr<int>') for 1st argument
    _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x);
                                   ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:699:36: note: 
      candidate function not viable: no known conversion from 'int *' to 'value_type' (aka
      'std::__1::shared_ptr<int>') for 1st argument
    _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x);
                                   ^
1 error generated.
like image 682
kmiklas Avatar asked Jan 10 '17 20:01

kmiklas


1 Answers

The std::shared_ptr<T> constructor that accepts raw pointers is marked explicit. source. You will not be able to call push_back with a raw pointer, as it's not implicitly convertible to std::shared_ptr<int> which is what push_back takes as an argument. The solution is to either use emplace_back instead of push_back or to use std::make_shared<int>.

emplace_back matches the parameters given to one of T's constructors.

w.emplace_back(new int(7));

std::make_shared<int> returns an object of type std::shared_ptr<int>, avoiding this problem.

w.push_back(std::make_shared<int>(7));

You may combine these solutions.

#include <iostream>
#include <vector>
#include <memory>

int main(int argc, char** argv) {
    std::vector<std::shared_ptr<int> > w;
    std::vector<std::shared_ptr<int> >::iterator it_w;
    w.emplace_back(std::make_shared<int>(7));

    std::cout << std::endl;
}

Edit: As an additional note, always prefer std::make_shared<T>(...) over std::shared_ptr<T>(new T(...)). It is designed to avoid very subtle potential memory leaks. It also elegantly avoids the situation where you have new without delete which may bother some people.

Edit 2: Additionally, std::make_shared<T>(...) has a performance advantage where it avoids an additional allocation in `std::shared_ptr(new T(...))' see this answer.

like image 175
François Andrieux Avatar answered Oct 22 '22 12:10

François Andrieux