at what point should I be passing a pointer to data in my functions/methods, rather than just passing the value?
Obviously there's the cases where I want the function to operate on the given data, but what if I'm just passing the value for info/copying purposes?
For example, foo as a basic type:
void setFoo(int foo);
...
int foo = 1;
setFoo(foo);
Now foo as a simple structure:
typedef struct {
int x;
int y;
} Foo;
void setFoo(Foo foo);
...
Foo foo = {1, 2};
setFoo(foo); // Apple code does this kind of thing with CGSize, CGPoint...
But what if foo is a bigger struct...
typedef struct {
int x;
int y;
int z;
char str[256];
} Foo;
void setFoo(Foo *foo); // Now taking a pointer instead.
...
Foo foo = {1, 2, 3, etc ... };
setFoo(&foo);
Q. At what point here should I start using a pointer when providing data to a function?
Thanks
When on embedded systems, I think it's good practice to pass pointers (or references) for anything that's not a primitive type. This way your struct can grow and add members as needed without affecting the amount of data that is copied. Needless copying is a good way to slow down your system, so avoid it when you can. Getting into that habit will help in the long run I think.
If you use references and/or pointers to [const] objects as appropriate, "when" becomes "all the time"
Related
I realize that similar questions have been asked elsewhere, but I couldn't find an answer that's a good fit for my function signatures.
Consider this typical pair of C functions:
int initFoo(Options options, Foo* foo);
void freeFoo(Foo* foo);
initFoo takes some options and a pointer to an uninitialized Foo struct. It initializes this struct and returns a result code that indicates whether the initialization was successful. freeFoo frees an initialized Foo struct.
Now assume I want to use these C functions in my C++ code. I want to use RAII, so I need to construct a unique_ptr<Foo> that will automatically call freeFoo on destruction. The best approach I could come up with is this:
template<typename T>
using lambda_unique_ptr = std::unique_ptr<T, std::function<void(T*)>>;
lambda_unique_ptr<Foo> createFoo(Options options) {
Foo* foo = new Foo();
const int resultCode = initFoo(options, foo);
if (resultCode != 0) throw ...;
return lambda_unique_ptr<Foo>(foo, [](Foo* foo) {
freeFoo(foo);
delete foo;
});
}
I'm certain that there must be a more elegant solution. Ideally, something more functional that doesn't require so many individual steps. What I find particularly ugly is the necessity to explicitly allocate the Foo struct on the heap, then explicitly free and delete it in two steps. Any ideas?
Can't you just wrap Foo in a class?
struct FooWrap {
Foo foo;
explicit FooWrap(Options options) {
if (initFoo(options, &this->foo))
throw ...;
}
~FooWrap() {
freeFoo(&this->foo);
}
// XXX: either implement or disable assignment and copy construction
};
Now you can choose whether to just define FooWrap x(42); as an automatic variable or whether to allocate it dynamically with new.
I know this is super basic, but will a non pointer value hold its value when it is initialized within a constructor?
class foo {
private:
int bar;
int cool;
public:
foo(int tBar);
~foo();
}
foo::foo(int tBar) {
bar = tBar;
cool = -5;
}
Or in other words, will bar hold tBar's value later on and will cool still be equal to 5 after the construction of the object?
Answer is Yes. I had a misconception that every member variable had to be a pointer!
BUT
When I use more complicated object types (like my own objects) it doesn't work this way. Why is that?
Answer is yes, the object will hold its value
Also I was using crappy objects. That is why they didn't hold value.
I have a function that takes a double pointer to a struct and assigns a value. However I get an "access violation writing location ..." when trying to access the member member1.
This is my code:
struct mystruct{
unsigned int member1;
void * data;
};
int main(){
mystruct **foo = new mystruct *;
bar(foo);
}
void bar(unsigned int val, mystruct ** foo)
{
(*foo)->member1 = val;
}
You just created a new mystruct pointer. That means:
You get allocated a memory block, large enough to hold a address, and assign it to the pointer which is pointing to a pointer that points to a mystruct member.
That doesn't mean, that there is a valid address hold in the pointer which you expect to be pointing to a mystruct element. Even more currently there isn't even a valid address, where the pointer to the pointer is pointing on, as you just assigned a valid memory area to it, what doesn't mean there is a usefull address stored in.
So at all, what you want is:
You want a pointer which has a valid memory block to store a address in of another pointer, which is pointing to a valid memory area, where is a (probably valid) mystruct stored in.
What you are doing is: you are requesting a memory area where you COULD (what you aren't even doing) store a poitner to another pointer... and so on.
so what you should do is:
mystruct **foo = new mystruct *;
*foo = new mystruct;
I have a function that takes a double pointer
That's weird. If you can, simplify it to take a reference:
void bar(unsigned int val, mystruct & foo) {
foo.member1 = val;
}
mystruct foo;
bar(42, foo);
If you don't have control over the function, then you'll need an object at the end of the pointer trail:
mystruct foo;
mystruct * pointless = &foo;
bar(42, &pointless);
You can, of course, mess around with new if you really want to; but that's almost certainly a bad idea.
Your code allocates and leaks a pointer, but doesn't initialise it to point to a valid object; so dereferencing it gives undefined behaviour.
This C-style function:
void bar1(mystruct* foo) {
foo->member1 = val;
}
takes an argument of type mystruct* in order for changes made to object that foo points to to be visible to the caller. However this function:
void bar(unsigned int val, mystruct ** foo) {
(*foo)->member1 = val;
}
takes pointer to mystruct* (most likely) in order to to modify the pointer itself, i.e. in order for changes made to the pointer to be visible to the caller and thus probably meant to be used this way:
mystruct* foo = new mystruct;
bar(&foo);
... yet usually it is reasonable to avoid dynamic allocation and passing pointers should be rather rarity than a common practice. Prefer objects with automatic storage duration over the dynamically allocated ones and prefer passing by reference over passing by pointer (when possible).
The other answers are good advice. But also, if you have control over the bar function, and need to be able to change in bar to what object your mystruct * pointer points to (which is probably the reason why you have a double pointer in the first place), then the cleanest approach is to use the following signature for bar:
void bar(unsigned int val, mystruct * &foo);
It passes by reference a pointer, so you are able to change to what object the pointer points to, without sacrificing readability of the code, for instance:
int main()
{
mystruct * foo = new mystruct;
bar(42, foo);
}
void bar(unsigned int val, mystruct * &foo)
{
foo->member1 = val;
foo = new mystruct;
}
A complete usage scenario without memory leak could be:
int main()
{
// allocate dynamically a mystruct whose member1 is equal to 1.
mystruct * foo1 = new mystruct;
mystruct * foo2 = foo1;
foo1->member1 = 1;
// pass by reference foo1
bar(42, foo1);
// here, foo1->member1 == 42 and foo2->member1 == 10
// free memory
delete foo1; // the one allocated in bar()
delete foo2; // the one allocated in main()
}
void bar(unsigned int val, mystruct * &foo)
{
// modify the object allocated in main()
foo->member1 = 10;
// allocate dynamically a mystruct, store its address in foo
foo = new mystruct;
foo->member1 = val;
}
I can't remember what it is called, but I know i can do it in Java.
Suppose I have the following:
class Foo
{
public:
Foo() {};
void bar() {};
};
I want to do this:
int main() {
(new Foo).bar();
}
But it doesn't seem to work. Is there a similar way to do this without having to do:
int main() {
Foo foobar;
foobar.bar();
}
new dynamically-allocates memory and returns a pointer. Class members are obtained using the indirection operator ->. I don't think this is what you're looking for as you run the risk of causing a memory leak. Simply calling the constructor of Foo allows us to do what we want:
Foo().bar();
By calling the constructor of Foo, we create a temporary object off of which we can obtain its data members. This is preferred over pointers as we don't have to deal with memory leaks and deletion of the pointer.
You can say (new Foo)->bar();. That works but is absolutely idiotic. The correct thing is this:
int main()
{
Foo x;
x.bar();
}
Or, if you don't want the local variable: Foo().bar();. But now that's questionable, since if you don't need Foo to be stateful, then you probably don't need a class at all. Just make bar a free function (something that doesn't exist in Java):
void bar();
int main()
{
bar();
}
Yes, Foo().bar();. No need to use new like in Java.
Wondering how to assign a pointer to an array member:
struct foo {
int INT;
}
int main() {
foo bar[10];
foo *baz;
baz = bar[5];
}
This does not work, but I am wondering what would.
Thank you much for any help.
You want to do baz = &bar[5];. bar[5] Refers to the 6th foo object instance itself, so just take the address (with the & operator) to assign to the pointer, same as any other situation;
Alternatively, you can also do baz = (bar + 5); since here bar used without a number is a pointer to the first element and +5 gives the 6th element.