2

I'm sure this question has been answered some where, and please link me to it if it has, but I'm struggling to find an answer to this exact question. There are many that are very close. Here are some I've already read that don't quite answer my question:

pass by reference and value with pointers Reason to Pass a Pointer by Reference in C++? Using delete on pointers passed as function arguments

Here is a basic outline of the situation, trying to make it pretty close to my actual usage:

void func (vector<int>* foo) {

    int bar = foo->at(0);

    // transform bar

    foo->at(0) = bar;

    // Should I delete foo?
    delete foo;
}

int main() {

    vector<int> data (4, 0);

    data.at(0) = 5;

    for (int i = 0; i > 10; i++) {

        func(&data);

    }
}

edit: the for loops above should read like this:

for (int i = 0; i < 10; i++) {

So, as you can see, I have created a vector called data, and then passed a reference of data to the function. The function gets a value from data via the reference, transforms it, and then saves the new value back to data again via the reference.

In this specific scenario, this function is the only function that receives this data, but it gets called repeatedly and passed the reference to the same data each time.

My main question is, should I delete foo at the end of that function? Also, if I had an extra function also being passed a reference to data, would that change the answer?

I have read other questions that suggest to be careful deleting a pointer in a function, but they have all related to a data type that was declared as a pointer in the first place. I am not declaring a pointer or reference in the first place, just creating a reference as an argument to the function (I think?).

The reason I ask this anyway, is that my program has some serious memory leaks. I've done some research, and read lots about pointer related memory leaks, and it's occurred to me this might be one source of it

I have tried adding a "delete" at the end of one such function, and all seems well, so far... but I don't want to add a whole bunch of deletes, then some time down the road find out that it was a really bad idea :D

Cheers in advance, Pete

Community
  • 1
  • 1
Iron Attorney
  • 862
  • 1
  • 8
  • 19

2 Answers2

5

You have to call delete for each new (except placement new which is special).

Here, no new, so no delete.

Jarod42
  • 173,454
  • 13
  • 146
  • 250
  • Ok, I really need to do some more research on pointers and references then. Why is a pointer/reference different if there is a call to new? I pressume that in my example, the pointer gets deleted at the end of each function call anyway? – Iron Attorney Dec 21 '15 at 18:55
  • `new` allocates memory and `delete` release corresponding memory. `vector data` is a local variable of `main` and its destructor is called at end of the `main` scope. – Jarod42 Dec 21 '15 at 18:59
  • Ok, that's cool. So will the pointer in the function get deleted at the end of each function call, and will the reference to data that is created in main be deleted at the end of main? Or is that reference never saved in the main function in the first place? I know pointers and references don't individually use up a great deal of space, but I have an aweful lot of these kind of shenanigans going on, and a sizeable memory leak. Is this not likely to be the cause? – Iron Attorney Dec 21 '15 at 19:09
  • ps, I want to upvote, but I don't have enough reputation. Sorry! – Iron Attorney Dec 21 '15 at 19:09
1

Should I delete foo?

No, you should not.

Moreover, you should never use new or delete. And you shold never pass value by pointer.

Instead, pass it by reference (&), if you want to change it in the function.

Correct code:

void func (vector<int> & foo) {

    try {
        int bar = foo.at(0);
    }
    catch (std::out_of_range) {
        // here you should process an exception 
        // when `foo` contains no elements
    }

    // transform bar

    foo.at(0) = bar;
}

int main() {

    vector<int> data (4, 0);

    data.at(0) = 5;

    for (int i = 0; i > 10; i++) {

        func(data);

    }
}

(Note: may be it must be i < 10 in loop?)

vladon
  • 7,412
  • 1
  • 35
  • 75
  • I wouldn't say to never pass by pointer. We have a convention where I work to pass output parameters by pointer to make it clearer to the caller that the argument is modified (they have to use `&` in the call). For everything else pass by value or by const reference. – Kevin Dec 21 '15 at 20:08
  • It's a bad convention originated from C (because C has no references at all). Correct rules are simple: pass cheap in-parameter by value, pass big in-parameter by `const &` (or, if you consume it in function, simply pass by value), pass in-out-parameter by non-const `&`, don't pass out-only-parameter, instead return from function by value (even big objects). See [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rf-conventional) for this. – vladon Dec 21 '15 at 20:14
  • As I said, it's a convention where I work, and I quite like it. To each his own, as long as you're consistent. – Kevin Dec 21 '15 at 20:18
  • @Kevin What's bad with that convention: 1) memory leaks; 2) segfaults; 3) possibility of passing `nullptr`s; 4) by `&Object` you cannot determine that you passing single object or array of objects (and cannot determine their sizes). It is VERY BAD and harmful in 2015, where C++14 already exists. – vladon Dec 21 '15 at 20:20
  • 1) What memory leaks? These are pointers to objects on the stack; 2+3) Yes you need to check for nullptr. But this gives the option of 'ignoring' output parameters without changing the calling convention; 4) These are pointers to single objects on the stack, they can be vectors or anything. I don't see anything harmful about it except for the slight annoyance of needing to dereferencing the parameter in the function. – Kevin Dec 21 '15 at 20:26
  • 4) How declaration `void func(Object *);` specify that it accepts single `Object` instance or array of `Object` instances? It is ambiguous. – vladon Dec 21 '15 at 20:28
  • Because in C++ you don't use raw arrays. You use `std::array` or `std::vector`. If it's a single object you'd do `void func(Object*)` and if it's an array you'd do `void func(std::vector*)` – Kevin Dec 21 '15 at 20:29
  • @Kevin 1) You may pass pointer, then use it uninitialized by new or accidentally delete it in BIG program or forgot to delete it. 2+3) Why check it if with references you must not do it? 4) How declaration `void func(Object *);` specify that it accepts single `Object` instance or array of `Object` instances? It is ambiguous. – vladon Dec 21 '15 at 20:30
  • @Kevin You wrote about C++ and use raw pointers from C? What? – vladon Dec 21 '15 at 20:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/98607/discussion-between-kevin-and-vladon). – Kevin Dec 21 '15 at 20:31
  • @Kevin And if you can do all checks in COMPILE time, why you want to do it at RUNtime? Sorry, don't want to chat now, it's about midnight in Russia. Good night. – vladon Dec 21 '15 at 20:32
  • Thanks for all the comments. Despite your disagreement, I feel I am still gaining from it. vladon would you say then that passing by pointer the way I have could be part of my memory leak issue? And yes, i did mean to write i < 10 :D @Kevin I am guessing you don't think passing by pointer should cause a memory leak? – Iron Attorney Dec 22 '15 at 13:43
  • 1
    @IronAttorney Just don't use pointers where you can use any other modern thing. Take it as a rule of thumb. It will save you from millions of possible errors. – vladon Dec 22 '15 at 13:45
  • 1
    Passing the address of a variable on the stack has no chance of a memory leak. There is no additional memory allocated, so there isn't any memory that you need to manually delete. The only unsafe thing about it is that the pointer could be null, which could be a feature if you want the caller to be able to do that. – Kevin Dec 22 '15 at 13:48
  • Ok cool, thanks alot. I'm glad you mention passing by reference btw, I've been confused for a while about the difference between references and pointers. I was more confused because I was passing &data to the function and recieving *foo in the function. I wondered if I was mixing up references and pointers, but the compiler liked it, so I went for it, haha. So I only need to pass the value and recieve it as a reference? – Iron Attorney Dec 22 '15 at 13:50
  • @Kevin, ok. I'm a bit disappointed, I was hoping it was the source of my memory leak. I may change my pointers to references anyway to see if it makes much of a difference to the program. If all runs smoothly, I guess I'll stick with the references. Thank you both for the advice! – Iron Attorney Dec 22 '15 at 13:52
  • @Kevin Passing a pointer instead of reference forces you to additional checks in code and in brain while coding. Passing reference instead of pointer helps you, because all checks are doing at compile-time, you cannot pass null pointer (of course, you can, but it is cannot be done accidentally). References (instead of pointers) save your time, nerves and make your hair silky. – vladon Dec 22 '15 at 13:55
  • @IronAttorney Think about references as *synonyms* for original variables, not as addresses. – vladon Dec 22 '15 at 13:56
  • Ok, that makes sense. One last question about it, is there any notable difference in performance between passing by pointers or passing by reference? – Iron Attorney Dec 22 '15 at 14:53
  • 1
    @IronAttorney Runtime code is the same, so performance is the same, too. But with pointers you need additional check to nullptr, so... – vladon Dec 22 '15 at 16:01