I am trying to create a function that allocates memory. It allocates it, but the problem is that it only appears to do so inside the function, but after it returns the memory allocated is no longer there. Almost as if I am allocating memory with another pointer, but there should be no other there.
template<class T> struct rmv_ptr { using type = T; };
template<class T> struct rmv_ptr<T*> { using type = T; };
template<class T> struct rmv_ptr<const T*> { using type = T; };
template<class T> bool alloc(T inst, int size)
{
return (nullptr != (inst = new typename rmv_ptr<T>::type[size]));
}
Say I call it like this:
wchar_t* a;
alloc(a, 10);
inst will be wchar_t*, so a's pointer should point to the allocate memory, no?
When you pass an integer to a function, you cannot change the integer.
When you pass a pointer to a function, you cannot change the pointer.
When you pass a pointer to a function, you can change the pointed-to value.
Pass-by-non-const-reference is the exception; it allows you to change the passed value. Passing a pointer by reference therefore allows you to change the pointer.
On an unrelated note, the base rule for "remove pointer" template logic won't work. The problem is that you have two uses of T. There's the argument T& inst, which has to match T* returned by new. I.e. if T is int, then rmv_ptr<int>::type is int, and new will return an int*. But you can't assign that int* to int& inst.
Pointers are no different from non-pointers as modifications are not visible outside when passed by value to a function:
void foo(int* p) { p = 0; } // only modifies the local p
void foo(int a) { a = 0; } // only modifies the local a
However, pointers allow you to modify what the pointer does point to and that can be observed by the caller:
// assume p points to an int
void bar(int* p) { *p = 42; }
This will not modify p itself. When called via
int x;
int xp = &x;
bar(xp);
then p inside bar is a copy of xp, though they both point to the same int.
But when you call new, then new returns you a pointer to the allocated memory, so you need to change the pointers value, not just the pointee. Either pass it by reference, or return the pointer from the function (making it a parameter is of no use anyhow).
Related
The type is defined:
typedef int (*vlc_media_player_is_playing(libvlc_media_player_t*));
The class defines a field with this type. The field is populated with the address of the function from the dll. When you try to call a function, the int* pointer is returned instead of int. Why is this happening?
Thus, in the pointer are the data correct.
When you try to dereference the pointer, the program
crashes.
I will also add that an example of this type:
typedef struct libvlc_instance_t libvlc_instance_t;
typedef libvlc_instance_t(*vlc_create_instance(int, const char* const*));
Somehow, too, returns a pointer at once.
class Foo
{
...
private:
vlc_media_player_is_playing* libvlc_media_player_is_playing = nullptr;
...
public:
Foo()
{
libvlc_media_player_is_playing = (vlc_media_player_is_playing*)GetSomeAddress("SomeFuncName");
}
void call()
{
// but this is not `int`
int result = libvlc_media_player_is_playing(player_ptr);
}
}
vlc_media_player_is_playing is an alias to a pointer to a function that returns an integer and takes a pointer to libvlc_media_player_t struct.
So any usage of this type is considered to be a pointer to function eg:
vlc_media_player_is_playing myFunc = SomeFuncReturningIntTakingVlc;
To call the function through the pointer eg:
int ret = (*myFunc)(libvlc_media_player_tParam);
But you created a pointer to a pointer to function here:
vlc_media_player_is_playing* libvlc_media_player_is_playing = nullptr;
So remove the pointer operator above to make it look like:
vlc_media_player_is_playing libvlc_media_player_is_playing = nullptr;
And to call the function later in your function call:
int result = (*libvlc_media_player_is_playing)(player_ptr);
I have code where I am trying to pass the underlying pointer of a unique_ptr in to a method accepting a pointer by reference:
unique_ptr<A> a;
func(a.get());
to call:
void func(A*& a){ // I am modifying what `a` points to in here
}
but I am getting compiler errors because get() is not returning what I expected was just the raw pointer. Is it possible to achieve what I am trying to do here?
No, and that's a good thing.
The problem is that get() returns an rvalue, not a reference to unique_ptr's internal pointer. Therefore you can't modify it. If you could, you would completely mess up unique_ptr's internal state.
Just pass a reference to the unique_ptr itself if you want to modify it.
A function that takes a pointer by reference is strongly hinting that it may reallocate/delete the pointer in question. That means it is asking for ownership responsibilities. The only safe way to call such a function is to release the pointer from the unique pointer and (possibly) reacquire it after the call.
// a currently manages (owns) the pointer
std::unique_ptr<A> a;
// release ownership of internal raw pointer
auto raw = a.release();
// call function (possibly modifying raw)
func(raw);
// (re)claim ownership of whatever func() returns
a.reset(raw);
But that can still be problematic if (say) the unique_ptr has a special deleter and the function doesn't re-allocate the object accordingly. Also if the function deletes the pointer without setting it to nullptr you will have a problem.
Here is an idea:
template<typename T> struct raw_from_ptr {
raw_from_ptr(T& pointer) : _pointer(pointer), _raw_pointer(null_ptr) {}
~raw_from_ptr() {
if (_raw_pointer != null_ptr)
_pointer.reset(_raw_pointer);
}
raw_from_ptr(pointer_wrapper&& _other) : _pointer(_other._pointer) {
std::swap(_raw_pointer, _other._raw_pointer);
}
operator typename T::pointer*() && { return &_raw_pointer; }
operator typename T::pointer&() && { return _raw_pointer; }
private:
T& _pointer;
typename T::pointer _raw_pointer;
};
template<typename T> raw_from_ptr<T> get_raw_from_ptr(T& _pointer) {
return raw_from_ptr<T>(_pointer);
}
Usage:
unique_ptr<A> a;
func(get_raw_from_ptr(a));
I recently saw a function that is being declared as:
void func(type* ¶m);
I already know the difference between type* param and type& param. How does the above differ from them? And when to use this? Is it advisable to do this?
The above will be able to modify not only the pointed object, but also the pointer in itself. As an example, consider the below code:
void func(int*& ptr) {
*ptr = 1;
ptr = 0;
}
int main() {
int x = 0;
int* y = &x;
func(y);
}
At the end of the execution, x has value 1 and y is 0 (as you can see).
Notice that for the sake of the example I've used 0 as a null pointer, but if you are using C++11 you should probably use nullptr instead (which does not have an overloaded operaror<< for std::ostream).
This concept can possibly be assimilated by taking a look at the following code:
template<class Type> using ptr = Type*;
ptr<int>& x;
or
std::unique_ptr<int>& x;
In these examples, x is a reference to a type (ptr<int> and then std::unique_ptr<int>), which just so happens to be a pointer/class with pointer semantic (operator* and operator->).
A possibly interesting digression can be made on the position of a const qualifier in the pointer. Consider these two instances:
void func(const int*& ptr)
void func(int*const& ptr)
Their meanings are:
pointer by reference to a constant int.
pointer by constant reference to an int.
And following the above analogy with ptr they would be:
ptr<const int>&
ptr<int> const&
Therefore the first will fail to execute *ptr = 1 in the body of the function (because the int is constant), but will happily execute ptr = 0.
The second will behave conversely, allowing *ptr = 1 (because the pointed int is not constant), while disallowing ptr = 0 (because the pointer is constant).
Of course, in the case of:
void func(const int*const& ptr)
which in the ptr analogy would be ptr<const int> const&, both of them wouldn't be allowed.
And when to use this? Is it advisable to do this?
Like every feature, you'll find its usefulness when you'll need it. But just as a general idea, some people used it to reset the pointer after freeing a dynamically allocated resource (I'm not recommending this, see below).
Let's take this example:
free_my_int(int*& ptr) {
delete ptr;
ptr = nullptr;
}
int* x = new int(42);
free_my_int(x);
At the end of the execution, x would be correctly freed and the pointer automatically set to nullptr (null pointer). This was done to prevent ugly segmentation faults or "pointer freed has not been allocated" error messages caused by a missing ptr = nullptr.
But with C++11 and C++14 there is very little use of pointers and even less of reference to pointers. Most of the things pointers where used for are not replaced with other standard construct (see std::optional, std::unique_ptr, std::shared_ptr or std::reference_wrapper for example).
Let's compare all three options:
void func(type* param); // 'param' is a 'type*' variable
void func(type& param); // 'param' is a reference to a 'type' variable
void func(type*& param); // 'param' is a reference to a 'type*' variable
void func(type* param)
{
type x;
...
param = &x;
// Argument 'param' is regarded as a local variable in this function,
// so setting 'param = ...' will have no effect outside this function
}
Of course, if you do *param = ..., then it will effect the contents of the memory pointed by param. And you can also do param[5] = ... for example, and effect other areas within that memory space.
void func(type& param)
{
type x;
...
param = x;
// Argument 'param' is regarded as a reference to a variable outside this
// function, so setting 'param = ...' will effect the referenced variable
}
Here, you will only change the referenced variable itself, so it's safer than declaring the function as void func(type* param), and then pass the address of type param by calling func(¶m).
void func(type*& param)
{
type x;
...
param = &x;
// Argument 'param' is regarded as a reference to a variable outside this
// function, so setting 'param = ...' will effect the referenced variable
}
This is similar to declaring the function as void func(type** param), and then pass the address of type* param by calling func(¶m), but again, it is safer for the same reason mentioned above.
So far to my understanding, when defining a pointer variable, we are allocating space in RAM for that variable.
int *p;
Would define a space in RAM. Then we assign a memory address to that pointer using `&variable'.
I'm looking over at an example on: *this vs this in C++
The code is:
#include <iostream>
class Foo
{
public:
Foo()
{
this->value = 0;
}
Foo get_copy()
{
return *this;
}
Foo& get_copy_as_reference()
{
return *this;
}
Foo* get_pointer()
{
return this;
}
void increment()
{
this->value++;
}
void print_value()
{
std::cout << this->value << std::endl;
}
private:
int value;
};
int main()
{
Foo foo;
foo.increment();
foo.print_value();
foo.get_copy().increment();
foo.print_value();
foo.get_copy_as_reference().increment();
foo.print_value();
foo.get_pointer()->increment();
foo.print_value();
return 0;
}
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does. Why do I get an error if I removed the * from the Foo* functions while returning this not *this?
edit:
Also, why is:
foo.get_copy().increment();
foo.print_value();
yielding 1 not 2?
I don't understand what the purpose of putting the * operator in front Foo* get_copy() and Foo* get_pointer() does
Foo* get_pointer()
Foo* is a pointer that points to Foo object.
this is also a pointer that implicitly bind to the calling object of the member function. That's why the return type of those functions are Foo* not Foo.
The * is part of the type. So int means type int, and
int* type pointer to int. If the function returns pointer
to int, it is int* foo(), and if it retu rns a pointer to
Foo, it is Foo* Foo::get_pointer().
The definition reserves space for the defined object. A
declaration doesn't reserve any space, and definitions of things
that aren't objects (e.g. references or functions) don't reserve
any space either, at least not that you can see. (Obviously, a
function does exist somewhere in memory, and in many cases, the
compiler will need space as well for its implementation of a
reference. But they are invisible within the scope of C++.)
this, is always a pointer in C++, though you don't mention it explicitly anywhere. So while returning a this pointer, should use Foo*
this is actually an implicit object passed during function call, which is a pointer to the object which calls the function
It seems that you have changed the code from the example that you refer to so that get_copy() no longer returns a copy.
There are 2 ways of using * in your code example. One is for type declaration and the other is the dereferencing operator.
First the type declarations:
int *p means declaring p as a variable of type "pointer to an int".
Foo *get_pointer() means that the function get_pointer will return a value of type "pointer to a Foo object".
Now the dereferencing:
*p means "the value that p points to".
int a = 42;
int *p; // p is of type "pointer to an int"
p = &a; // set p to the address of a (p now "points to" a)
a = 117; // change the value of a
int x = *p; // set x to the value that p points to (which is a) - x will be 117
this is just a pointer to the object. *this means "the object that this points to". In your example this is of type Foo* (pointer to a Foo object) while *this is of type Foo (a Foo object).
"this" is a pointer.
you want to return a pointer to the instance (a specific allocated object).
Foo* get_pointer(){
return this;
}
or you want to return a pointer to the copy, allocate a new object.
//need to implement the copy here
Foo* get_copy(){
return this;
}
and not to the reference (address of the instance). this is why you need to return the pointer.
I would pass T*& pointer, when I am intending to change the pointed value inside the function:
void foo(char *&p)
{
p = (b == true)? new char[10] : 0;
}
But I am not able to get what is the use case for T* const& kind of pointer (since that pointer is not changeable)? I mean why should not I pass simply T* const ?
void foo(char* const &p); // p is not changeable
void foo(char* const p); // p is not changeable
You would use a T* const & as a parameter if the value of the pointer object might be changed by something external to your function and you wanted to be able to observe changes to the value of the pointer object or if you wanted to store a reference or pointer to the pointer object for later reading.
A T* parameter (equivalent to T* const as a function parameter) just gives you a copy of the pointer object, a snapshot of its value when it was passed to your function.
void foo( char* const& ptr )
{
char* p1 = ptr; // initial value
global_fn(); // ptr might be changed
char* p2 = ptr; // new value of ptr
}
vs
void foo2( char* ptr )
{
char* p1 = ptr; // initial value
global_fn(); // ptr can't be changed, it's local to this function
char* p2 = ptr; // will be the same as p1
}
Technically, even the function itself might change the value of the pointer to which it is passed a reference.
E.g.
char* p;
std::ptrdiff_t foo( char* const& ptr )
{
++p;
return p - ptr; // returns 0, would return 1 if the parameter was by value
}
int main()
{
char test[] = "Hello, world!";
p = test;
foo( p );
}
The difference is realistically nil. const references are used to prevent copying of expensive-to-copy or, in generic code, uncopyable types, but since pointers are trivial, it's negligible and you may as well take by value.
I think a simpler example would illustrate the point that Charles Bailey is making. Let's remove the issue of the pointer part of it, because for this question it is irrelevant. So your question basically becomes:
void foo(const int &p); // p is not changeable
void foo(const int p); // p is not changeable
Do you see more clearly how it works? Yes, the local variable "p" cannot be assigned to in both cases. And yes, neither piece of code will affect the variable in the calling scope. But in the former example p could be a reference to a variable (non-const) int that can be changed while the latter is an argument passed by value which could not be changed. (Actually the const in the second example has no effect on anything outside the function, so it is kind of superfluous. Same with the second example in the question.)