views:

1775

answers:

2

I am just starting with C++ and got some problems in understanding how the scope for private member variables in a class works. Please see the below code

class Foo{
    private:
        std::vector<int> container;
    public:
        // other methods
};

int main(int argc, char* argv[])
{
    Foo* foo = new Foo;
    // other method calls to which foo is passed
    delete foo;
    return 0;
}

In the above code, variable "container" is a private member variable. I am invoking "Foo" instance and passing it to several other methods and classes. Following are my doubts

  1. What will be the scope of variable "container"? Will that variable exist until I delete the instance foo?
  2. Do I need to make the "container" as a pointer to vector?

Thanks for the help

+5  A: 
  1. Yes, the lifetime of the container member will last as long as the object that contains it exists, which is until you call delete on the pointer pointing to it (foo in your case).
  2. No, there is no reason to do that. Making it a pointer requires you to create a dynamic object of vector<int> which you would need to manage the lifetime of (including calling delete on the container pointer). That's unnecessary here. Assuming you want the container last as long as the Foo object, you are fine with having it directly contained, without doing it with a pointer.

Passing the foo pointer will just pass the pointer. The object that it points to will not be copied, only the pointer pointing to it if necassary. If you know Java, then it helps you if i tell you passing the pointer is the same as just passing a reference to an object in Java, say:

Foo f = new Foo();
// just passes the reference (pointer in C++) to doIt. 
// the actual object is not copied
doIt(f);
Johannes Schaub - litb
Damn, litb, when do you sleep? :)
Alastair
Great answer. Many thanks. Some doubts on memory allocation1 - foo will be allocated on heap, right?2 - Where the container variable goes?
Appu
1) yes2) container is *inside* the foo, so it is wherever the foo is.
Ray Tayek
Thanks. But as container don't have any memory allocated by "new", how it will goto the location where foo is?
Appu
well. it's done implicitly. by saying "new Foo" you allocate memory for all the members of foo. the compiler will know by your call to delete that its members were allocated in memory created by new, and will free that memory.
Johannes Schaub - litb
in c++ we say that the data members of a class object do have the same storage duration as the class objects. three of those exist (overview in a hurry, not quite precise): static (for globals), dynamic (for objects created by new) and automatic (for objects created on the stack).
Johannes Schaub - litb
Thanks litb. So to conclude, varible "container" will also be allocated on heap along with "Foo" instance and compiler will take care about the initialization and destruction of variable "container". Is that right? Thanks
Appu
A: 

I am invoking "Foo" instance

Actually, you are creating an instance of class Foo.

Specifically, you are allocating a block of memory off the heap via new(). This block of memory is large enough to contain Foo::container and whatever other overhead class Foo requires.

(In this example, there is none. With other classes, there might be additional attributes or perhaps a virtual-pointer table.)

Naturally, new() invokes the (perhaps default?) Foo::Foo() constructor, which in turn initializes Foo::container through the std::vector constructor.

What will be the scope of variable "container"?

container is an attribute [component] of the instance foo. It exists as long as the instance foo exists.

Scope-wise, we can speak of Foo::container. But you cannot access Foo::constainer without an instance of class Foo. (E.g. The object foo.) Foo::constainer doesn't exist without an instance of class Foo.

(There are class-variables that work somewhat differently, where one value is shared across all instances. But that is not the case here.)

This scoping is IRRELEVANT to your public/protected/private/friend member-access-control.

E.g., in some Foo::myPublicMethod() you could refer to Foo::container. Though you could also forgo the explicit scoping in this situation and just refer to it as container.

Mind you, being private, you can't access Foo::container outside of class Foo's methods.

Will that variable exist until I delete the instance foo?

Yes.

Do I need to make the "container" as a pointer to vector?

No. You can, but you certainly don't have to.

Generally speaking, I recommend against class instance members being pointers coupled with new in the constructor and delete in the destructor. It's inefficient and troublesome. (The default copy constructor can copy the pointer value, the destructor can then delete the same pointer value twice.)


Depending on your needs, you might consider:

int main(int argc, char* argv[])
{
  Foo foo;
  // other method calls to which foo is passed
  return 0;
}

foo would go out of scope after return 0;, and be automatically deleted. Moreover, foo would be allocated off the stack rather than the heap.


You might find a used copy of The Annotated C++ Reference Manual useful. It's old, but it has a high signal-to-noise ratio.

Mr.Ree
ah, good catch. maybe he didn't even want to use new at all
Johannes Schaub - litb
To add to this answer, when you pass the local `foo` to the other functions you should use a reference to avoid copying `foo`. The function signature should look like `void useFoo(Foo `. Not only does this prevent copying, it also guarantees to `useFoo` that it's argument will never be null, reference can not be null. If the function doesn't modify the `foo` parameter, then define it as `void useFoo(const Foo `.
joshperry
Of course the problems of null pointers and copying the object are mutually exclusive problems...
joshperry
It's up to the programmer whether they want to copy foo (deep or shallow copy), or use a (perhaps const?) reference/pointer to the original. Both have their uses and costs. Const-references work better with temporaries. A null-reference is undefined in the C++ spec, but not necessarily outlawed by the compiler. Using a null-reference will get you ostracized. Relying on null-reference never occurring can get you hurt.
Mr.Ree