0

I'm a newbie using V++ and I've been wondering about some memory behavior.
I wrote similar classes to what is causing me problems. The questions are written in the comments of the code.

class A
{
private:
    int _number;
public:
    A(int number) : _number(number)
    {}

    const int& getNumber() const
    {
        return _number;
    }

    void setNumber(const int& number)
    {
        _number = number;
    }
}

class B
{
private:
    A _a;
    bool _hasA;

public:
    B() : _hasA(false)
    {}

    B(const A & a) : _a(a), _hasA(true)
    {}

    void setA(const A & a)
    {
        _a = a;
    }

    const A& getA() const
    {
        return _a;
    }

    const bool hasA() const
    {
        return _hasA;
    }

    void removeA()
    {
        // ??
    }
}

int main()
{
    A a(5);

    B b1; // Is the A space allocated even if no value is affected to it ?
    B b2(a);

    b1.setA(b2.getA()); // I actually want to move "a" from b2 to b1 without leaving it in b2
    b1.removeA(); // Do I need to write a removeA() function and how would it be?
}

b1.setA(b2.getA()); copies A into b1 too instead of moving it.

Thanks for your help.

EDIT: To answer those who are confused like I just was:

Me : I just understood that when instanciating b1 it needed the A::A() constructor. I thought it'd be like "null" or something if I created b1 without instantiating _a.

Zac Howland: @SanjamX I see your confusion now. In managed languages, (most) everything is a pointer, so if you do not instantiate it (e.g. A a instead of A a = new A()), it is just a null pointer. In C/C++, if you declare something as A a, you instantiated it "on the stack". It is an automatic variable that will be deallocated when it goes out of scope. You are still instantiating it, however. This question may help you understand better.

Community
  • 1
  • 1
Majid
  • 654
  • 2
  • 7
  • 28
  • 2
    Have you tried to compile it? (hint: it won't compile, there are several errors) Note: `B b1();` is a function declaration ("most vexing parse"); either use C++11's `B b1{};` or just `B b1;`. – dyp Jan 21 '14 at 21:06
  • 1
    I don't see any point in your code, where it's necessary to free allocated memory? It will be all done pretty well on the stack? – πάντα ῥεῖ Jan 21 '14 at 21:07
  • with b1.setA(b2.getA()); A will be copied to b1. Will they share the same pointer? I want to move A to b1 and not copy it. In other terms, I want it to be deleted from b2. – Majid Jan 21 '14 at 21:09
  • May be `removeA()` could just get off with setting `_hasA` to false, and assign `_a` to some reasonable default value (if that's needed at all). The design smells somehow though! – πάντα ῥεῖ Jan 21 '14 at 21:10
  • _'Will they share the same pointer?'_ It's **copied** ...!! – πάντα ῥεῖ Jan 21 '14 at 21:12
  • This isn't really "the design", I just wrote this code to express the allocation problems I was having. As I wrote in the first question, when declaring, will it allocate space in the memory for A even though it isn't instanciated ? – Majid Jan 21 '14 at 21:14
  • 2
    @SanjamX _'to express the allocation problems'_ The code you show **has no allocation problems**! – πάντα ῥεῖ Jan 21 '14 at 21:16
  • 1
    @πάνταῥεῖ Exception safety is one of the big design smells with the 2-step approach. – Zac Howland Jan 21 '14 at 21:16
  • 1
    @SanjamX On the line you asked about, it won't allocate anything because it isn't declaring a variable, but a function. If you were to have `B b1;`, it would allocate space for both an `A` and a `bool` (which is what you have in class `B`) because you *are* instantiating it. Are you coming from a managed language background by chance? – Zac Howland Jan 21 '14 at 21:18
  • 1
    Indeed, I am. And the b1() was a mistake, I edited it when it was notified to me. – Majid Jan 21 '14 at 21:21
  • I just understood that when instanciating b1 it needed the A::A() constructor. I thought it'd be like "null" or something if I created b1 without instanciating _a. – Majid Jan 21 '14 at 21:30
  • 1
    @SanjamX I see your confusion now. In managed languages, (most) everything is a pointer, so if you do not instantiate it (e.g. `A a` instead of `A a = new A()`), it is just a null pointer. In C/C++, if you declare something as `A a`, you instantiated it "on the stack". It is an automatic variable that will be deallocated when it goes out of scope. You are **still** instantiating it, however. [This question](http://stackoverflow.com/questions/10823454/declaring-a-variable-vs-dynamically-assigning-memory-to-a-variable-in-c) may help you understand better. – Zac Howland Jan 21 '14 at 21:34
  • I can see that now. I'll read the question. thanks! – Majid Jan 21 '14 at 21:36

1 Answers1

3
B b1();

That does not do what you think it does. It is declaring a function b1 that takes no parameters and returns a B.

b1.setA(b2.getA());
b1.removeA();

Because of the previous situation, the 2 lines above will give you a compiler error.

The "move" you are asking about will actually be a copy (in this case). You can use the C++11 move semantics to do an actual move, but it is entirely unnecessary with the current code. Alternatively, you can change your class to do a move using pointers (which could potentially be useful) - which would use std::unique_ptr<A> _a, instead of A _a.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • the "move" from std will swap values between what's in b1::_a and b2::_a ? What if I want to delete what's b2::_a ? – Majid Jan 21 '14 at 21:11
  • 1
    @SanjamX There's nothing to _'swap'_ actually!! Declare an appropriate move constructor otherwise. – πάντα ῥεῖ Jan 21 '14 at 21:15
  • @SanjamX No, it will not swap them. If you move it, it is moved. I think you would be better served to use the `std::unique_ptr` solution as there is no need to move anything in your current code. – Zac Howland Jan 21 '14 at 21:15