2

I have the following constructor:

MutexWrapper::MutexWrapper(Mutex * pMutex)
{
  DebugPrint("0x%x", pMutex); // displays 0x1f83e54
}

And it gets called in the following function:

void OnReviewBuffer_Callback( void * pUserData )
{
  ReviewBuffer * thePointer = (ReviewBuffer *) pUserData;

  DebugPrint("0x%x", thePointer); // this displays 0x1f83e48

  MutexWrapper theMutexWrapper(thePointer);
}

Unfortunately I can't provide the entire definition of ReviewBuffer - but I hope the below is enough:

class ReviewBuffer  : public StreamConsumer_Base, public Mutex
{
  ...
};

The problem is that when I print out thePointer I get 0x1f83e48, but the value printed from inside the constructor is 0x1f83e54.

Why are the pointer values different - is this something to do with pass by value passing in a copy of the pointer?

BeeBand
  • 10,237
  • 19
  • 58
  • 83

3 Answers3

5

Your class ReviewBuffer uses multiple inheritance:

class ReviewBuffer  : public StreamConsumer_Base, public Mutex
{
  ...
};

The internal layout of the class (probably*) looks like this:

Offset 0    class StreamConsumer_Base
            ... contents of that class (12 bytes including alignment: 0x1f83e54 - 0x1f83e48)
Offset 12   class Mutex
            ... contents of that class (unknown size)

(*) probably because nothing in the standard mandates this. This is just the usual way compilers implement it.

When you initially print thePointer, it points to the ReviewBuffer object ie. offset 0 of the class. But when you pass it to your function, the pointer automatically gets adjusted by the compiler to point to the Mutex part of ReviewBuffer. Since that Mutex part is at offset 12, the value of the pointer cannot be the same (think about it: if it was the same, it would not point to a Mutex but to either a ReviewBuffer or a StreamConsumer_Base).

syam
  • 14,333
  • 3
  • 39
  • 65
2

Your non-default constructor MutexWrapper::MutexWrapper takes a Mutex* pointer as an argument. Your function OnReviewBuffer_Callback casts the provided void* pointer to a ReviewBuffer* pointer. The only way you can pass that ReviewBuffer* pointer as an argument to MutexWrapper::MutexWrapper(Mutex*) is if ReviewBuffer is a derived class of Mutex. If ReviewBuffer also inherits from other classes, downcasting a ReviewBuffer* pointer to a Mutex* pointer may result in a pointer with a different address than the original. That is exactly what's going on, based on the latest edit. ReviewBuffer uses multiple inheritance.

David Hammen
  • 31,392
  • 8
  • 57
  • 102
-1

In C++ as in Java, pointer are passed by value. Pass-by-reference is a misnomer.

Of course, pointer pointing to the same address variable, it looks like the whole is passed-by-reference, but...isn't.

Mik378
  • 21,449
  • 13
  • 75
  • 170
  • 3
    "Pass-by-reference is a misnomer [in C++]" **Defend this statement**. – John Dibling May 20 '13 at 15:14
  • 1
    There are no references here. The pointer is passed by value but (apparently) has a different value in the function. (And I've no idea what you mean by a "misnomer"; pass-by-reference is well defined in C++, it's just not happening here). – Mike Seymour May 20 '13 at 15:17
  • http://stackoverflow.com/questions/4426474/is-passing-pointer-argument-pass-by-value-in-c – Mik378 May 20 '13 at 15:17
  • 1
    This would only hold if the debug print printed the address of the pointer, but it looks like it should be printing the value of the pointer. – juanchopanza May 20 '13 at 15:17
  • @juanchopanza, Yes I interpreted differently the question, you're right. – Mik378 May 20 '13 at 15:18
  • 3
    @JohnDibling Well I'm somebody who absolutely avoids saying "pass by reference" when passing a pointer by value. The terminology has come over from C and is just confusing when applied to C++, particularly because we actually have reference types. The `Mutex` isn't being passed by reference; it's not being passed at all. In fact, the pointer that is passed (by value) needn't even be pointing at a `Mutex` object. This is only really a criticism of how the question is tagged though, and this answer doesn't really apply to the question itself. – Joseph Mansfield May 20 '13 at 15:21
  • @sftrabbit: Passing a pointer by-value, as is done in the OP, is not passing by-reference. – John Dibling May 20 '13 at 15:24
  • 2
    @JohnDibling The question is tagged [tag:pass-by-reference], though, as though the asker thinks passing a pointer is passing by reference (which *is* what C programmers say). This is what Mik378 is referring to in his answer by saying "pass-by-reference is a misnomer". – Joseph Mansfield May 20 '13 at 15:24
  • @sftrabbit - no, I just couldn't find the pass-by-value tag - i have changed it. – BeeBand May 20 '13 at 15:25
  • @Mik378: Your link does not defend an assertion that there is no pass-by-reference in C++. Please elaborate what you mean, exactly, when you say that "Pass-by-reference is a misnomer [in C++]" – John Dibling May 20 '13 at 15:25
  • @sftrabbit: I see. I hadn't noticed that tag on the question before you pointed it out. Mik378, is this what you're referring to? Or are you really saying there is no pass-by-reference in C++? – John Dibling May 20 '13 at 15:29
  • @John Dibling First, maybe and surely I merely misread (too quickly?) the question, as I said in one comment just above. I expected the user wanted to assert that the address of the original pointer still remains unchanged after passing it by method argument. Thus, in this typical interpretation, I wanted to inform that passing a pointer doesn't mean that the pointer itself is not passed by value. In this case, someone would pass the address of the pointer (as shown in the 0x499602D2's answer). Sorry for this wrong interpretation by the way. – Mik378 May 20 '13 at 15:31
  • @Mik378: Thanks for the clarification. – John Dibling May 20 '13 at 15:34