int main ()
{
shared_ptr<int[]> a(new int[2]);
a.get()[0] = 5;
a.get()[1] = 10;
int* foo = a.get();
++foo;
cout << *foo << endl;
return 0;
}
The output is "10" as i expected. But I used regular pointer (int* foo) how can i implement/use ++ operator with only shared_ptr.
A std::shared_ptr contains two parts:
A pointer to the bookkeeping.
A payload-pointer which should be valid at least as long.
So, for your pointer-arithmetic, just use a dependent shared_ptr setting both individually:
shared_ptr<int[]> foo(a, a.get() + 1);
As an aside, an array-shared_ptr supports indexing, so no need to go over .get() for that.
Also, as long as you keep one shared_ptr aroud to keep the data live, there is nothing wrong (actually, it is expected and more efficient) with using raw pointers and references for processing.
There isn't another way.
The only method is to call get and the increment it in the copy returned from the get.
I attach you some usefull link :
smartpointer - shared_ptr
cppreference.com - shared_ptr
What you are trying to do is semantically meaningless. A shared_ptr expresses the intent to own something (in this case an array of two int's). All it does is track ownership. If you increment a shared_ptr, does that mean you release the ownership of the first int? Or does it mean you own the second int twice? Either way is not what you are trying to do.
In general, use unique_ptr/shared_ptr only for ownership issues. To manipulate and use the memory directly, use a view class, something like a span. Not all compilers have this facility yet, so may have to use either the GSL library or write your own. However you implement it, it is better to make a separate object that views the object, but does not claim to own it. If you can tie the length of the array to pointer, this is better still.
Related
This question was discussed a few times but all those discussions almost a decade old and there was no good solution. The question is the same.
We have smart pointers, like unique_ptr, that is great. We have tons of C functions returning a pointer to an object as an argument which later needs to be released.
Let's say this is the function:
int CreateSomething(OBJECT_TYPE** pObject);
So, what would we normally do without smart pointers? Apparently something like that:
OBJECT_TYPE* pObject;
if(CreateSomething(&pObject) == 0) {
// Use the pObject pointer
delete pObject;
}
Now, I would like to rewrite it using smart pointers, and I would like it to be as simple as this:
unique_ptr<OBJECT_TYPE> pObject;
if(CreateSomething(&pObject) == 0) {
// Use the pObject pointer
}
Technically, that would be quite possible if unique_ptr would have T** operator&, and if it would count on this kind of workflow, but it doesn't.
In the case when we want to use a smart pointer here, we have to declare a regular pointer, use it in that function, and then reassign it to the smart pointer. But those extra steps can and should be eliminated, and I hope that maybe there is already an implementation which would allow me to do what I need in that simple manner as I showed.
Yes, I can write my own smart pointer or mediator, which would simplify the usage of unique_ptr, but first I'd like to ask if maybe there is already something implemented in the depth of standard libraries for this and I simply overlooked it?
C++23 has very recently added std::out_ptr for exactly this use case.
write a wrapper: (uncompiled code)
namespace smart_ptrs {
std::unique_ptr<OBJECT_TYPE> CreateSomething() {
OBJECT_TYPE *p = nullptr;
if (::CreateSomething(&p))
return std::unique_ptr<OBJECT_TYPE>(p);
return std::unique_ptr<OBJECT_TYPE>();
}
Then you can write:
std::unique_ptr<OBJECT_TYPE> ptr = smart_ptrs::CreateSomething();
if (ptr) {
// Use the pObject pointer
}
In the case when we want to use a smart pointer here, we have to declare a regular pointer, use it in that function, and then reassign it to the smart pointer.
Basically, yes. That is exactly what you must do (for now anyway, until std::out_ptr is added in C++23).
C++ smart pointers simply do not expose access to their held pointer, thus no way for you to obtain its address to pass to the C function. So, you have to use the smart pointer's constructor or assignment operator instead, which requires the object pointer to already be initialized first.
I'd like to ask if maybe there is already something implemented in the depth of standard libraries for this and I simply overlooked it?
You have not overlooked anything.
I am reading a lot of different things on C++ optimization and I am getting quite mixed up. I would appreciate some help. Basically, I want to clear up what needs to be a pointer or not when I am passing vectors and structures as parameters or returning vectors and structures.
Say I have a Structure that contains 2 elements: an int and then a vector of integers. I will be creating this structure locally in a function, and then returning it. This function will be called multiple times and generate a new structure every time. I would like to keep the last structure created in a class member (lastStruct_ for example). So before returning the struct I could update lastStruct_ in some way.
Now, what would be the best way to do this, knowing that the vector in the structure can be quite large (would need to avoid copies). Does the vector in the struct need to be a pointer ? If I want to share lastStruct_ to other classes by creating a get_lastStruct() method, should I return a reference to lastStruct_, a pointer, or not care about that ? Should lastStruct_ be a shared pointer ?
This is quite confusing to me because apparently C++ knows how to avoid copying, but I also see a lot of people recommending the use of pointers while others say a pointer to a vector makes no sense at all.
struct MyStruct {
std::vector<int> pixels;
int foo;
}
class MyClass {
MyStruct lastStruct_;
public:
MyStruct create_struct();
MyStruct getLastStruct();
}
MyClass::create_struct()
{
MyStruct s = {std::vector<int>(100, 1), 1234};
lastStruct_ = s;
return s;
}
MyClass::getLastStruct()
{
return lastStruct_;
}
If the only copy you're trying to remove is the one that happen when you return it from your factory function, I'd say containing the vector directly will be faster all the time.
Why? Two things. Return Value Optimisation (RVO/NRVO) will remove any need for temporaries when returning. This is enough for almost all cases.
When return value optimisation don't apply, move semantics will. returning a named variable (eg: return my_struct;) will do implicit move in the case NRVO won't apply.
So why is it always faster than a shared pointer? Because when copying the shared pointer, you must dereference the control block to increase the owner count. And since it's an atomic operation, the incrementation is not free.
Also, using a shared pointer brings shared ownership and non-locality. If you were to use a shared pointer, use a pointer to const data to bring back value semantics.
Now that you added the code, it's much clearer what you're trying to do.
There's no way around the copy here. If you measure performance degradation, then containing a std::shared_ptr<const std::vector<int>> might be the solution, since you'll keep value semantic but avoid vector copy.
So to illustrate my question I have made an example:
#include <iostream>
using namespace std;
struct A
{
void doSomething (){
cout << "Something\n";
}
};
struct B
{
A a;
A *getA ()
{
return &a;
}
};
int
main ()
{
B *b = new B ();
A *a = b->getA ();
// POINT 1
if (nullptr != a)
{
a->doSomething ();
}
delete b;
b = nullptr;
// POINT 2
if (nullptr != a)
{
a->doSomething ();
}
return 0;
}
This compiles and runs without errors on my machine, but if you inspect the code, really there is a problem of a dangling pointer on the lines following the comment marked "POINT 2".
Since b was deleted, then a is now invalid (since it was deleted by dtor of b).
So I could use a shared pointer to remedy this, but that would keep the instance of a around even after b was deleted, and also I would not be able to allocate a on the stack. These are two things I want to avoid. Instead I simply want to know if a is still valid.
I could also have used a unique pointer but then I could only have one single instance of a which is not what I want either, I want many copies of the pointer to a.
So is there some existing pointer/reference type that would allow me to do this? Are there any reason why this is a good/bad idea?
You have just discovered the wonders of ownership semantics :)
How to solve this problem depends on the design of your application: what you need and what you are trying to achieve.
In this case, if you really want to share ownership of an object, use std::shared_ptr which keeps a reference count of how many pointers are left, so that the last deletes the object; possibly std::weak_ptr if you only need to check if the object is still alive but don't want to keep it alive longer than needed.
However, do note that (ab)using shared pointers may be a sign of a bad design.
By the way, your A a; member is not allocated in the stack (i.e. the title is wrong).
Only viable solution using standard library that come in mind is to use std::weak_ptr() - it will allow to check object validity without holding it's ownership. That comes with price - you have to maintain ownership of it with std::shared_ptr. Though it is possible to create std::shared_ptr to an object with automatic storage duration and noop deleter I would do that only if I really need that as such method is error prone and defeats the purpose of a smart pointer.
The best way is to not expose a.
Your B is the interface. Give it the functions you need to perform. Have it go on to invoke whatever it needs to invoke on the a in order to make that happen.
Then remove getA(), and make a private.
Now it's completely encapsulated and the calling scope cannot arse around with it like this!
No need for pointers or dynamic allocation; just good, old-fashioned OOP.
I want to ask about passing pointers between functions or between objects or returning them .. I heard that passing or returning pointers in general (whether they point to an array or an object or whatever they are pointing at) isn't safe and the output isn't guaranteed.
now I've tried it and so far everything seems OK but I don't want my project to work by accident .. so can someone explain to me why not to pass or return pointers and what are the suggested solution (for example, what if I want to modify the same object (say object1) in a function in another object (function func in object2))?
also, I read in a tutorial that everything in c++ is pass by value? isn't passing pointers is called pass by reference?
Thanx everybody.
I want to ask about passing pointers between functions or between objects or returning them .. I heard that passing or returning pointers in general (whether they point to an array or an object or whatever they are pointing at) isn't safe and the output isn't guaranteed.
Where did you get that from? In general, it's not true and of course you can pass around pointers.
The tricky thing is managing ownership of (heap-allocated) objects, since somewhere you have to release the memory again. In other words: When you allocate memory with new, you will have to free it again with delete.
Example:
A* function1(A* a) {
return a;
}
B* function2(B* b) {
return new B(b);
}
function1 returns an existing pointer. Whoever owned the A object passed in will also own the returned one, as it is the same. This needs to be documented since this knowledge is essential for using function1!
function2 creates a new object of class B by coping its input argument. Whoever calls function2 will own the returned object and will be responsible to delete it when it's done. Again, this needs to be documented!
also, I read in a tutorial that everything in c++ is pass by value? isn't passing pointers is called pass by reference?
Technically, passing pointers is pass-by-value since the pointer itself gets copied. But since a pointer is a "reference type", you essentially get pass-by-reference with that.
Note that C++ also knows references (int&), which really is pass-by-reference.
Well, the honest answer is that people sometimes mean different things when they say "pass by reference".
But generally, when people say "pass by reference", they mean this:
void readInt(int &a) {
cin >> a;
}
int a;
readInt(a);
cout << a;
And "pass by pointer" would be this:
void readInt(int *a) {
cin >> *a;
}
int a;
readInt(&a);
cout << a;
Ultimately, you can use pointers for everything that references are used for (they other way around is mostly true).
Some people like references because they can use the . operator, like they normally do. Others prefer pointers because they are explicit.
Note that pointers are older than references (C does not have references), so C libraries will use pointers exclusively.
Most people (I think) use references when they can (like in your hypothetical example). The nice thing is that type safety will stop you if you confuse references and pointers.
I'd much prefer to use references everywhere but the moment you use an STL container you have to use pointers unless you really want to pass complex types by value. And I feel dirty converting back to a reference, it just seems wrong.
Is it?
To clarify...
MyType *pObj = ...
MyType &obj = *pObj;
Isn't this 'dirty', since you can (even if only in theory since you'd check it first) dereference a NULL pointer?
EDIT: Oh, and you don't know if the objects were dynamically created or not.
Ensure that the pointer is not NULL before you try to convert the pointer to a reference, and that the object will remain in scope as long as your reference does (or remain allocated, in reference to the heap), and you'll be okay, and morally clean :)
Initialising a reference with a dereferenced pointer is absolutely fine, nothing wrong with it whatsoever. If p is a pointer, and if dereferencing it is valid (so it's not null, for instance), then *p is the object it points to. You can bind a reference to that object just like you bind a reference to any object. Obviously, you must make sure the reference doesn't outlive the object (like any reference).
So for example, suppose that I am passed a pointer to an array of objects. It could just as well be an iterator pair, or a vector of objects, or a map of objects, but I'll use an array for simplicity. Each object has a function, order, returning an integer. I am to call the bar function once on each object, in order of increasing order value:
void bar(Foo &f) {
// does something
}
bool by_order(Foo *lhs, Foo *rhs) {
return lhs->order() < rhs->order();
}
void call_bar_in_order(Foo *array, int count) {
std::vector<Foo*> vec(count); // vector of pointers
for (int i = 0; i < count; ++i) vec[i] = &(array[i]);
std::sort(vec.begin(), vec.end(), by_order);
for (int i = 0; i < count; ++i) bar(*vec[i]);
}
The reference that my example has initialized is a function parameter rather than a variable directly, but I could just have validly done:
for (int i = 0; i < count; ++i) {
Foo &f = *vec[i];
bar(f);
}
Obviously a vector<Foo> would be incorrect, since then I would be calling bar on a copy of each object in order, not on each object in order. bar takes a non-const reference, so quite aside from performance or anything else, that clearly would be wrong if bar modifies the input.
A vector of smart pointers, or a boost pointer vector, would also be wrong, since I don't own the objects in the array and certainly must not free them. Sorting the original array might also be disallowed, or for that matter impossible if it's a map rather than an array.
No. How else could you implement operator=? You have to dereference this in order to return a reference to yourself.
Note though that I'd still store the items in the STL container by value -- unless your object is huge, overhead of heap allocations is going to mean you're using more storage, and are less efficient, than you would be if you just stored the item by value.
My answer doesn't directly address your initial concern, but it appears you encounter this problem because you have an STL container that stores pointer types.
Boost provides the ptr_container library to address these types of situations. For instance, a ptr_vector internally stores pointers to types, but returns references through its interface. Note that this implies that the container owns the pointer to the instance and will manage its deletion.
Here is a quick example to demonstrate this notion.
#include <string>
#include <boost/ptr_container/ptr_vector.hpp>
void foo()
{
boost::ptr_vector<std::string> strings;
strings.push_back(new std::string("hello world!"));
strings.push_back(new std::string());
const std::string& helloWorld(strings[0]);
std::string& empty(strings[1]);
}
I'd much prefer to use references everywhere but the moment you use an STL container you have to use pointers unless you really want to pass complex types by value.
Just to be clear: STL containers were designed to support certain semantics ("value semantics"), such as "items in the container can be copied around." Since references aren't rebindable, they don't support value semantics (i.e., try creating a std::vector<int&> or std::list<double&>). You are correct that you cannot put references in STL containers.
Generally, if you're using references instead of plain objects you're either using base classes and want to avoid slicing, or you're trying to avoid copying. And, yes, this means that if you want to store the items in an STL container, then you're going to need to use pointers to avoid slicing and/or copying.
And, yes, the following is legit (although in this case, not very useful):
#include <iostream>
#include <vector>
// note signature, inside this function, i is an int&
// normally I would pass a const reference, but you can't add
// a "const* int" to a "std::vector<int*>"
void add_to_vector(std::vector<int*>& v, int& i)
{
v.push_back(&i);
}
int main()
{
int x = 5;
std::vector<int*> pointers_to_ints;
// x is passed by reference
// NOTE: this line could have simply been "pointers_to_ints.push_back(&x)"
// I simply wanted to demonstrate (in the body of add_to_vector) that
// taking the address of a reference returns the address of the object the
// reference refers to.
add_to_vector(pointers_to_ints, x);
// get the pointer to x out of the container
int* pointer_to_x = pointers_to_ints[0];
// dereference the pointer and initialize a reference with it
int& ref_to_x = *pointer_to_x;
// use the reference to change the original value (in this case, to change x)
ref_to_x = 42;
// show that x changed
std::cout << x << '\n';
}
Oh, and you don't know if the objects were dynamically created or not.
That's not important. In the above sample, x is on the stack and we store a pointer to x in the pointers_to_vectors. Sure, pointers_to_vectors uses a dynamically-allocated array internally (and delete[]s that array when the vector goes out of scope), but that array holds the pointers, not the pointed-to things. When pointers_to_ints falls out of scope, the internal int*[] is delete[]-ed, but the int*s are not deleted.
This, in fact, makes using pointers with STL containers hard, because the STL containers won't manage the lifetime of the pointed-to objects. You may want to look at Boost's pointer containers library. Otherwise, you'll either (1) want to use STL containers of smart pointers (like boost:shared_ptr which is legal for STL containers) or (2) manage the lifetime of the pointed-to objects some other way. You may already be doing (2).
If you want the container to actually contain objects that are dynamically allocated, you shouldn't be using raw pointers. Use unique_ptr or whatever similar type is appropriate.
There's nothing wrong with it, but please be aware that on machine-code level a reference is usually the same as a pointer. So, usually the pointer isn't really dereferenced (no memory access) when assigned to a reference.
So in real life the reference can be 0 and the crash occurs when using the reference - what can happen much later than its assignemt.
Of course what happens exactly heavily depends on compiler version and hardware platform as well as compiler options and the exact usage of the reference.
Officially the behaviour of dereferencing a 0-Pointer is undefined and thus anything can happen. This anything includes that it may crash immediately, but also that it may crash much later or never.
So always make sure that you never assign a 0-Pointer to a reference - bugs likes this are very hard to find.
Edit: Made the "usually" italic and added paragraph about official "undefined" behaviour.