Wednesday, September 30, 2009

comp.lang.c++ - 13 new messages in 6 topics - digest

comp.lang.c++
http://groups.google.com/group/comp.lang.c++?hl=en

comp.lang.c++@googlegroups.com

Today's topics:

* about new and delete - 2 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/85fc26a34c7b73d3?hl=en
* overloaded assignment - 3 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/4e45d60a4d77d8fe?hl=en
* trouble with STL list initialization inside nested structure - 3 messages, 3
authors
http://groups.google.com/group/comp.lang.c++/t/232c5d7f8d6e70f5?hl=en
* A few questions about singletons... - 2 messages, 2 authors
http://groups.google.com/group/comp.lang.c++/t/dd7f3af258a800cd?hl=en
* Pass a pointer variable to a function accept reference - 2 messages, 1
author
http://groups.google.com/group/comp.lang.c++/t/330170d81fae3d1c?hl=en
* problem with template - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/3794de606deb5029?hl=en

==============================================================================
TOPIC: about new and delete
http://groups.google.com/group/comp.lang.c++/t/85fc26a34c7b73d3?hl=en
==============================================================================

== 1 of 2 ==
Date: Tues, Sep 29 2009 2:49 pm
From: Sam


Juha Nieminen writes:

> Sam wrote:
>> Juha Nieminen writes:
>>
>>>> No, not "clearly". There are a number of situations where the
>>>> contortions one must go through, in order to use a vector as the
>>>> underlying container, more than negate any inherent vector-specific
>>>> optimizations.
>>>
>>> And what might those be?
>>
>> Where existing iterators to container members must remain valid after an
>> insert (or a delete) from the container.
>>
>> Duh.
>>
>>> And how are they relevant to the original post?
>>
>> That's going to be your homework assignment for today.
>
> I don't need to do that "homework" because you yourself answered the
> question above, by giving an imaginary example which is certainly not

Very interesting. So a situation where one needs all existing iterators to
remain valid, after an element gets added to the container, are "imaginary",
and will never happen in practice. Gee, why would you *possibly* want
something like that?

Well, that's a comforting thought.

== 2 of 2 ==
Date: Tues, Sep 29 2009 3:14 pm
From: Sam


Juha Nieminen writes:

> Sam wrote:
>> Juha Nieminen writes:
>>
>>>> And what is the complexity of removing an element from the middle of the
>>>> list, versus the middle of a vector?
>>>
>>> O(n) for both.
>>
>> Hahahahahaha.
>>
>> std::list<obj> theList;
>>
>> // …
>>
>> std::list<obj>::iterator p;
>>
>> // …
>>
>> theList.erase(p); // Warning, O(n)!!!!!
>>
>> Very funny.
>
> That's not O(n) or O(1).

Not according to you, it is.

> That's Undefined Behavior because you haven't
> initialized p to anything.

Free honking clue: the "// …" parts specifies bits of code left out of the
example, for brevity.

> You conveniently left out the initialization of p. Please show me how
> you initialize p to point to the exact middle of theList.

Well, just for shits and giggles:

theList.push_front(obj());

p=theList.front();

// … (for a smaller value of …)

theList.erase(p); // Warning, O(n), according to Juha!!!!!

Happy now?

>>
>> What you fail to grok, is that when you have a member of containe that
>> you want removed, you already have its iterator, you don't need to
>> search for it.
>
> What do you mean I already have its iterator? No I don't.

That's why nobody will let you write production code :-)

> Please show me how you get that iterator. You claim that removing an
> object from the middle of a list is O(1). Prove it to me. You are so
> smart that it shouldn't be a problem to you.

I'm very smart. If I add objects to a list, that I know that I'll want to
remove later, I'll save their iterator, someplace, so when I need to remove
it, I won't need to search for it.

That's why they pay me the big bucks, Grasshopper.

>> You're just grasping at straws here, desperately trying to create a
>> contrived situation that fits your preconceived notions.
>
> I don't think it's very contrived: Write a C++ function which takes a
> std::list as (a reference) parameter, and removes the element in the
> exact middle of the list.

I'll write it as soon as I lose the ability to write entire applications
correctly.

See, I have a habit of writing actual code, rather than homework
assignments. For the purpose of producing a homework assignment that
correctly implements a given task, the most efficient solution is not a
factor, that's why you get this kind of inane demands.


>> This is
>> something that will often occur inside ivory halls of academia, where
>> brownie points are awarded for completing a purely theoretical excersize
>> that bears no relevance to anything that will occur in practice.
>
> Yes, in practice you will never need to, for example, pick elements
> from a container in random order, without repetitions (and of course as
> fast as possible).

Of course you do. Happens all the time. I/O is rarely predictable. If you're
dealing with a server implementation that multiplexes between multiple
clients, you'll never end up getting client disconnections in strict reverse
chronological order to client connections.

>> Well, how about the "Unlike you, I have actually *measured* in practice
>> the memory usage of std::vector vs. std::list" part, referring to your
>> argument that std::vector always wins?
>
> There you go again with the "always wins". You failed to quote me
> saying "always wins" because I have not written that. That's entirely in
> your imagination.
>
> Your claim seems to be that std::list is superior to std::vector
> because std::list consumes less memory.

No, my claim is that that std::list does not always consume more memory that
std::vector. That's your claim, which I debunked.

Free clue: "std::list does not always consume more memory than std::vector"
is not logically equivalent that "std::list always consumes less memory than
std::vector".

> this is a false statement in many, if not even most cases. That's
> exactly what I did. I never said that "std::vector always wins".

Gee, I'm having some difficulty finding any other statement from you, in
this thread. Care to help me find them?

>>> See? Look who is changing the topic.
>>
>> The individual who first brought up dequeue. Hint: it wasn't me.
>
> I find it hilarious that when std::deque beats your beloved std::list
> in all possible ways, you try to shrug it off with some ridiculous
> meta-argument about changing topics.

Your sense of humor is a bit bizarre, then. You've just shrugging off me
pointing out that it was you who changed the topic by bringing up deque in
the first place, yet you don't find /that/ funny. How come?

>
>> "fastest" != "always fastest". Elementary, my dear Watson, elementary.
>
> Pushing back into a std::deque is, as far as I can see, *always*
> faster than pushing back into a std::list. Please show me otherwise.

"As far as I can see" is a revealing hint that you are not necessarily
convinced of that yourself. Your homework assignment (since you're so fond
of them), is to find the cases when it's not.

>
>>> Besides, as I said, inserting and deleting from the middle of a list
>>> is O(n).
>>
>> No, it's not. See 23.2.2.3:
>>
>> Complexity: Insertion of a single element into a list takes constant
>> time and exactly one call to the copy constructor of T.
>> …
>>
>> Complexity: Erasing a single element is a constant time operation with
>> a single call to the destructor of T.
>
> Then please give me the function which removes the element in the
> exact middle of a std::list in constant time. Show me some *practical*
> code, rather than relying on *theoretical* claims.

You know perfectly well how you've been nailed to the wall on this one.
Removing elements from a list is O(1), and flapping your arms and throwing a
bunch of extra conditions and requirements is not going to change the basic,
underlying fact.

> When you say "removing *from the middle* can be done in constant time"
> you are conveniently skipping the part where you have to actually get an
> actual iterator pointing to the middle. You are only focusing on the

And you are conveniently ignoging the part where you don't need to "get" an
iterator, since you've already "got" it, when you added the object to the
list in the first place.

I think that the disconnect here is that you're not really familiar with
std::list, you've rarely used it, so you are ignorant of how to properly use
this container in practice. So, you're operating under an impression that
std::list is just some black hole where one dumps objects into, and when one
needs to find them, you have to search for them, every time. This probably
stems from your lack of experience with iterators, which are used
extensively in conjunction with std::list.

So you end up asking absurd questions about something that will never happen
in practice, and are utterly inane.

> There are even more practical situations where O(n) random access of
> lists becomes an issue. For example if you would want to write a
> function which splits a list into two equal parts: You have to get to
> the middle before you can splice it. The splicing itself being O(1) is
> of little help here.

If one needs a container, and a part of the requirements is to be able to
split it in half like that, as efficiently as possible, then what one would
do is implement a special container that's designed for that specific
purpose, Grasshopper.

And I'm dying to know how you're planning to accomplish the same feat with
your beloved std::vector: splitting it into two smaller ones, each half the
original's size, efficiently. With constant complexity.

Do that, and I'll nominate you for the Nobel prize.

Because, from the first look at this, std::list will spank the monkey of
std::vector, thanks to std::list::splice!

Copying half the vector's contents into another vector, than truncating the
original vector, would be O(n).

Iterating over the entire list is also O(n), however it's just iteration,
while with std::vector, you'll end up doing a shitload of copy constructor
and destructor calls, after you finish iterating. While with std::list, you
just call std::splice, which is O(1)!!!

You still have much to learn, Grasshopper!

==============================================================================
TOPIC: overloaded assignment
http://groups.google.com/group/comp.lang.c++/t/4e45d60a4d77d8fe?hl=en
==============================================================================

== 1 of 3 ==
Date: Tues, Sep 29 2009 3:15 pm
From: aegis


Consider the following:

#include <iostream>

using namespace std;

class X {
public:
X& operator=(const X& o)
{
if(this != &o) {
a = o.a;
}
return *this;
}
X() { a = 10; }
void set(int val) { a = val; }
int get() { return a; }
private:
int a;
};
int main(void)
{
X x;
x.set(100);
X p = x;
cout << p.get() << endl;
return 0;
}


If I change a = o.a in the overloaded assignment method,
then I get the following from g++:
g++ -o t t.cpp
t.cpp: In method `X &X::operator= (const X &)':
t.cpp:10: passing `const X' as `this' argument of `int X::get ()'
discards qualifiers

What this is saying is that because my 'o' is of type:
const X&, then get() method discards the qualifier.

But does it really? In addition, if I modify the prototype
of 'get()' to: int get() const, then I have no problem.
Yet why should this matter as the return type of 'get'
is the object type 'int'?

== 2 of 3 ==
Date: Tues, Sep 29 2009 3:31 pm
From: Sam


aegis writes:

> Consider the following:
>
> #include <iostream>
>
> using namespace std;
>
> class X {
> public:
> X& operator=(const X& o)
> {
> if(this != &o) {
> a = o.a;
> }
> return *this;
> }
> X() { a = 10; }
> void set(int val) { a = val; }
> int get() { return a; }
> private:
> int a;
> };
> int main(void)
> {
> X x;
> x.set(100);
> X p = x;
> cout << p.get() << endl;
> return 0;
> }
>
>
> If I change a = o.a in the overloaded assignment method,

Change to what? I deduce that you meant that you've changed it to
"a=o.get();".

> then I get the following from g++:
> g++ -o t t.cpp
> t.cpp: In method `X &X::operator= (const X &)':
> t.cpp:10: passing `const X' as `this' argument of `int X::get ()'
> discards qualifiers
>
> What this is saying is that because my 'o' is of type:
> const X&, then get() method discards the qualifier.

Yes.

> But does it really? In addition, if I modify the prototype
> of 'get()' to: int get() const, then I have no problem.
> Yet why should this matter as the return type of 'get'
> is the object type 'int'?

Because what a particular class method does is irrelevant, as far as
correctness is concerned. If you have a constant object reference (or a
pointer), you can only invoke the object's constant methods, using that
reference/pointer. What a particular method does or does not bears to
relation on whether the compiler will or will not complain that your code is
correct, according to the C++ language specification.


== 3 of 3 ==
Date: Tues, Sep 29 2009 3:40 pm
From: "Francesco S. Carta"


On 30 Set, 00:15, aegis <ae...@mad.scientist.com> wrote:
> Consider the following:
>
> #include <iostream>
>
> using namespace std;
>
> class X {
> public:
> X& operator=(const X& o)
> {
> if(this != &o) {
> a = o.a;
> }
> return *this;
> }
> X() { a = 10; }
> void set(int val) { a = val; }
> int get() { return a; }
> private:
> int a;};
>
> int main(void)
> {
> X x;
> x.set(100);
> X p = x;
> cout << p.get() << endl;
> return 0;
>
> }
>
> If I change a = o.a in the overloaded assignment method,
> then I get the following from g++:
> g++ -o t t.cpp
> t.cpp: In method `X &X::operator= (const X &)':
> t.cpp:10: passing `const X' as `this' argument of `int X::get ()'
> discards qualifiers
>
> What this is saying is that because my 'o' is of type:
> const X&, then get() method discards the qualifier.
>
> But does it really? In addition, if I modify the prototype
> of 'get()' to: int get() const, then I have no problem.
> Yet why should this matter as the return type of 'get'
> is the object type 'int'?

Declaring "get()" as "get() const" you are telling the compiler (and
the users of your class) that "get()" will not modify the object upon
which that method is called. It is actually good practice to declare
methods which do not modify the objects as const - sometimes it is not
just good practice, but necessary. Read the FAQ about const-
correctness & co.

By the way, there isn't really any need to create an assignment
operator if a shallow, compiler-generated assignment operator will
work just fine.

Anyway, I've recently been taught that protecting a class from self
assignment isn't really a good pick, unless you're implementing your
assignment operator in a weird manner - you're slowing down the
assignment to protect against something which, in this case, isn't
harmful at all, that is, assigning "a" to itself.

These issues should be detailed further, and eventually other posters
will give you better insights on them, but we have had some
discussions about these issues, recently, you could take advantage of
searching the threads about them (search for the copy-swap idiom).

Have good time,
Francesco
--
Francesco S. Carta, hobbyist
http://fscode.altervista.org

==============================================================================
TOPIC: trouble with STL list initialization inside nested structure
http://groups.google.com/group/comp.lang.c++/t/232c5d7f8d6e70f5?hl=en
==============================================================================

== 1 of 3 ==
Date: Tues, Sep 29 2009 3:43 pm
From: M A


Thanks for the explanation Joshua. I wasn't aware of intricate
differences between "malloc" and "new"!
I just made a quick fix as follows:
------------------------------------

typedef struct pattern {
int nodenum; // unique in the graph
MyStruct ms;
} TP;

int main(int args, char **argv)
{

TP *tp = new TP;

struct row r1 = {1, (char *)"xyz"};

tp->ms.bm.push_back(r1);

list<struct row>::iterator itr = tp->ms.bm.begin();

cout << (*itr).rowid << " " << (*itr).data << endl;
}
-------------------------------------
And it is working now.
Thanks a lot for your help. :)


On Sep 29, 5:26 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote:
> On Sep 29, 2:17 pm, M A <medha.a...@gmail.com> wrote:
>
> > Hi,
>
> > Please see following code.
> > It gives me segmentation fault when I try to add element to the list
> > on the very last line. I am not sure why the "bm" list inside MyStruct
> > is not getting initialized? What can I do to initialize it?
>
> > Thanks.
>
> [snip code]
>
> > TP *tp = (TP *) malloc (sizeof(TP));
>
> this is not the same as
>   TP *tp = new TP;
> The first does not call any constructors. The second calls TP::TP, the
> constructor, which also calls the constructor of all sub-objects,
> including the std::list member sub-object. Without calling the
> constructor of std::list, attempting to do anything with it is
> undefined behavior. std::list::list() constructor sets up invariants
> and internal data members.
>
> You seem to be coming from a C background. I'd suggest a picking up a
> good book on C++.

== 2 of 3 ==
Date: Tues, Sep 29 2009 4:03 pm
From: "Francesco S. Carta"


On 30 Set, 00:43, M A <medha.a...@gmail.com> wrote:
> Thanks for the explanation Joshua. I wasn't aware of intricate
> differences between "malloc" and "new"!
> I just made a quick fix as follows:
> ------------------------------------
>
> typedef struct pattern {
>         int nodenum; // unique in the graph
>         MyStruct ms;
>
> } TP;
>
> int main(int args, char **argv)
> {
>
>         TP *tp = new TP;
>
>         struct row r1 = {1, (char *)"xyz"};
>
>         tp->ms.bm.push_back(r1);
>
>         list<struct row>::iterator itr = tp->ms.bm.begin();
>
>         cout << (*itr).rowid << " " << (*itr).data << endl;}
>
> -------------------------------------
> And it is working now.
> Thanks a lot for your help. :)


Consider replacing C-style strings with std::string - if you really
come from a C background you will have to put apart some of the tricks
needed by C. Most of the explicit memory management gets done behind
the curtains by the STL containers, take advantage of them, when you
write in C++.

Also, learn to replace all C-style casts with C++ explicit casts -
you'll learn also that most of the times you don't need casting at
all. For example, conversions get normally done with functional
notation:
-------
int i = 10;
double d = double(i) / 3;
-------

Once I'm here: don't top post. It messes up replies and some users
gets a bit upset for them.

You can learn a lot of things about C++ and about comp.lang.c++ by
reading the FAQ: http://www.parashift.com/c++-faq-lite/

Have good time,
Francesco
--
Francesco S. Carta, hobbyist
http://fscode.altervista.org


== 3 of 3 ==
Date: Wed, Sep 30 2009 12:14 am
From: SG


M A wrote:
>
> typedef struct {
>         list<struct row> bm;
>         vector<struct row> vbm;
>
> } MyStruct;

This is a mixture of C and C++. You could write just as well

struct MyStruct {
list<row> bm;
vector<row> vbm;
};

> typedef struct pattern {
>         int nodenum; // unique in the graph
>         MyStruct ms;
> } TP;

same here

> int main(int args, char **argv)
> {
>         TP *tp = (TP *) malloc (sizeof(TP));
>         struct row r1 = {1, (char *)"xyz"};
>         tp->ms.bm.push_back(r1);
> }

same here. Replace malloc with new and char* with std::string. Also, I
don't see a reason for using the free store. This should work too:

int main(int args, char **argv)
{
TP tp;
row r1 = {1, "xyz"}; // note: no "struct" prefix
tp.ms.bm.push_back(r1);
}

By the way: In C++ string literals are const. So, you better use
"const char*" instead of "char*". The latter one still compiles for
backwards compatibility to C. Since you're now allowed to modify the
characters of a string literal (not even in C) you'll only gain from
using const qualifiers here.

One last note: Try to improve encapsulation.

Cheers,
SG

==============================================================================
TOPIC: A few questions about singletons...
http://groups.google.com/group/comp.lang.c++/t/dd7f3af258a800cd?hl=en
==============================================================================

== 1 of 2 ==
Date: Tues, Sep 29 2009 4:48 pm
From: "Chris M. Thomasson"


"Michael Doubez" <michael.doubez@free.fr> wrote in message
news:5b98df17-4599-49bc-ba58-a5a31cc1d800@k17g2000yqb.googlegroups.com...
On 25 sep, 20:45, Joshua Maurice <joshuamaur...@gmail.com> wrote:
[...]

> > Alternatively, use the more complex designs of Chris M.
> > Thomasson, which just guarantee single correct construction with
> > minimal overhead. There are several, depending on platform, and
> > exactly what guarantees you want.

> I have seen the code mentioned and it supposes that initialisation of
> the mutex is atomic.

> If I replace in the header:
> typedef HANDLE pthread_mutex_t;
> #define PTHREAD_MUTEX_INITIALIZER CreateMutex(/* params */)
> You see the problem with:
> static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;

> In fact, it is possible that two mutex will be created and the mutex
> is then useless.

> In practice, IIRC it does work with the usual libpthread.

Yes. The code I posted assumes that it will always be run under a POSIX
compliant platform. However, since you bring up Windows, well, there is a
hack one can use to dynamically and safely create a mutex in an atomic
fashion:
____________________________________________________________________
class win_dcl_mutex
{
HANDLE m_mutex;


private:
static std::string prv_get_name()
{
std::ostringstream name;

name << "DCL_MUTEX_" << GetCurrentProcessId();

return name.str();
}


public:
win_dcl_mutex() throw()
: m_mutex(CreateMutex(NULL, TRUE, prv_get_name().c_str()))
{
if (! m_mutex)
{
assert(m_mutex);
std::unexpected();
}

else if (GetLastError() == ERROR_ALREADY_EXISTS)
{
if (WaitForSingleObject(m_mutex, INFINITE) !=
WAIT_OBJECT_0)
{
assert(m_mutex);
CloseHandle(m_mutex);
std::unexpected();
}
}
}

~win_dcl_mutex() throw()
{
if (! ReleaseMutex(m_mutex))
{
assert(m_mutex);
CloseHandle(m_mutex);
std::unexpected();
}

if (! CloseHandle(m_mutex))
{
assert(m_mutex);
std::unexpected();
}
}
};
____________________________________________________________________


You would use this hack in the slow path of the DCL algorithm. You can make
this technique more fine grain by adding something to the constructor which
would further identify this mutex beyond using the current process id.
Something like:
____________________________________________________________________
class win_dcl_mutex
{
HANDLE m_mutex;


private:
template<typename T>
static std::string prv_get_name(T const& id)
{
std::ostringstream name;

name << "DCL_MUTEX_" << GetCurrentProcessId() << "_" << id;

return name.str();
}


public:
template<typename T>
win_dcl_mutex(T const& id) throw()
: m_mutex(CreateMutex(NULL, TRUE, prv_get_name(id).c_str()))
{
if (! m_mutex)
{
assert(m_mutex);
std::unexpected();
}

else if (GetLastError() == ERROR_ALREADY_EXISTS)
{
if (WaitForSingleObject(m_mutex, INFINITE) !=
WAIT_OBJECT_0)
{
assert(m_mutex);
CloseHandle(m_mutex);
std::unexpected();
}
}
}

~win_dcl_mutex() throw()
{
if (! ReleaseMutex(m_mutex))
{
assert(m_mutex);
CloseHandle(m_mutex);
std::unexpected();
}

if (! CloseHandle(m_mutex))
{
assert(m_mutex);
std::unexpected();
}
}
};
____________________________________________________________________


[...]

== 2 of 2 ==
Date: Tues, Sep 29 2009 4:57 pm
From: Joshua Maurice


On Sep 29, 4:21 am, Michael Doubez <michael.dou...@free.fr> wrote:
> On 25 sep, 20:45, Joshua Maurice <joshuamaur...@gmail.com> wrote:
> > On Sep 25, 1:05 am, Michael Doubez <michael.dou...@free.fr> wrote:
> > > You can use a Meyer singleton which solve the initialisation order
> > > issue:
> > >
> > > static CSingleton& GetInstance()
> > > {
> > >  CSingleton static_instance;
> > >  return static_instance;
> > > }
> > >
> > > And the cleanup is made at termination. The cleanup of a singleton is
> > > delicate because you don't known how is currently using it (it is even
> > > worse when in a DLL); you should let the system decide when it is no
> > > longer needed.
> >
> > Suffice to say, actually suggesting the simplest Meyer's singleton is
> > bad advice. Frankly, I've made so many mistakes on this topic recently
> > that I'll just point you to the thread where someone more
> > knowledgeable than me suggests more correct ways to do this.
> >
> > http://groups.google.com/group/comp.lang.c++/browse_thread/thread/bca...
> >
> > 1- Your singleton may cause static deinit issues. If you can leak it,
> > just leak it. Otherwise, it'll work correctly if all other statics
> > call getSingleton in their constructors. This will guarantee correct
> > destruction order, Last In First Out.
>
> You mean if a static gets latter on (after its initialisation) a
> reference on the singleton ?

Yes.

> This is not limited to singleton but to
> every storage management; have seen some case where the singleton is
> resetable causing that kind of problem but it is more related to the
> logic of the program(er).
>
> Betting on a singleton with the longest lifetime does guarantee your
> program doesn't crash for this reason but it is IMHO at best a patch.

Agreed.

> > 2- It's not thread-safe. There's the simple ways to do this correctly
> > which come with the caveat that "No nontrivial threads during static
> > init".
>
> That is alas true. The next standard does provide atomic operations
> which will ease that pain (I hope).

IIRC: Even better: all initializors of namespace-scope variables and
static-local variables will have pthread_once semantics. It'll also
give basic atomic operations as well.

> > Alternatively, use the more complex designs of Chris M.
> > Thomasson, which just guarantee single correct construction with
> > minimal overhead. There are several, depending on platform, and
> > exactly what guarantees you want.
>
> I have seen the code mentioned and it supposes that initialisation of
> the mutex is atomic.
>
> If I replace in the header:
> typedef HANDLE pthread_mutex_t;
> #define PTHREAD_MUTEX_INITIALIZER CreateMutex(/* params */)
> You see the problem with:
> static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
>
> In fact, it is possible that two mutex will be created and the mutex
> is then useless.
>
> In practice, IIRC it does work with the usual libpthread.

I got this very wrong in the aforementioned thread. Chris does a good
job correcting me there. You are right that PTHREAD_MUTEX_INITIALIZER
has no (easy) windows equivalent. Check out the code Chris posted in
the aforementioned link. He covers this case as well.

Although, honestly, at this point I would just strongly suggest using
Boost's pthread_once wrapper, which basically uses Chris's windows
implementation for windows IIRC.

==============================================================================
TOPIC: Pass a pointer variable to a function accept reference
http://groups.google.com/group/comp.lang.c++/t/330170d81fae3d1c?hl=en
==============================================================================

== 1 of 2 ==
Date: Tues, Sep 29 2009 4:55 pm
From: "Louis"


Hi Pascal:

Thanks for you reply;

Few more question if you dont mind.

In my case passing pointer variable to function is the best using a pointer
reference or a raw pointer?

int test(int *&temp)
{
(*temp)++;
cout << *temp << endl;
}

int test(int *temp)
{
(*temp)++;
cout << *temp << endl;
}

\\main
int c = 1;
int *d = &c;
test(d);

and you mentioned
/*
The difference is that take_a_raw_pointer will accept temporary
pointers returned by functions, while take_a_pointer_reference will
want a pointer variable.
*/
still a bit confuse
do u mean using raw pointer, temp will modify the same address where d
pointing to?
while using pointer reference, temp will modify the reference of d...?

Thanks
L


----- Original Message -----
From: "Pascal J. Bourguignon" <pjb@informatimago.com>
Newsgroups: comp.lang.c++
Sent: Tuesday, September 29, 2009 7:01 PM
Subject: Re: Pass a pointer variable to a function accept reference


> "Louis" <islouis@hotmail.com> writes:
>
>> Hi all:
>>
>> Im having a little bit confuse of passing a pointer variable to a
>> function that accept reference:
>>
>> void test(int &temp)
>> {
>>
>> temp+= temp + 2;
>>
>> cout << "function:" << temp << endl;
>> cout << "function:" << &temp << endl; //c:0x22ff1c
>> }
>>
>> int main(int argc, char *argv[])
>> {
>>
>> int c = 0;
>> int *d = &c;
>> cout << "d:" << *d << endl;
>> test(*d); // i guess, *d is dereference of d, which is value of c,
>> and same as int &temp = c, like passing reference?
>> cout << "c:" << &c << endl; //function:0x22ff1c,
>> return 0;
>> }
>>
>> it works, i guess, *d is dereference of d, which is value of c, and
>> same as int &temp = c, like passing reference?
>>
>
>
> Perhaps you could get a hint from the character used to denote a
> reference: &
>
> When you write: int &temp; temp = c; int x =
> temp;
> what actually happen is like: int * temp; temp = &c; int x =
> *temp;
>
> int x = *temp;
> <=> int x = *&c; // since temp = &c
> <=> int x = c; // since *& = identity.
>
> You may consider the reference variables as pointers that are
> automatically deferenced everytime they're used.
>
>
>> In the above code i'm trying to pass a dereference pointer d, which is
>> contain value of c, can anyone can explain to me if this is a good way
>> to pass a pointer variable?
>
> You didn't pass a pointer, you passed an int.
> To pass a pointer you'd have to use the *.
>
>
> void take_a_raw_pointer (int* param){
> (*param)=42; // modifies the int pointed to by param.
> param=0; // modifies param.
> }
>
> void take_a_pointer_reference(int*& param){
> (*param)=42; // modifies the int pointed to by the pointer referenced
> by param.
> param=0; // modifies the pointer referenced by param.
> }
>
> /*
> The difference is that take_a_raw_pointer will accept temporary
> pointers returned by functions, while take_a_pointer_reference will
> want a pointer variable.
> */
>
> int* p=&c;
> int* compute_some_int_pointer();
>
> take_a_raw_pointer(&c);
> take_a_raw_pointer(p); // p cannot be modified assert(p==&c);
> take_a_raw_pointer(compute_some_int_pointer());
>
> take_a_pointer_reference(p); // p might be modified and be null or point
> to another int than c.
>
>
> --
> __Pascal Bourguignon__
"Pascal J. Bourguignon" <pjb@informatimago.com> wrote in message
news:7cvdj2jdwq.fsf@pbourguignon.lefevre.anevia.com...
> "Louis" <islouis@hotmail.com> writes:
>
>> Hi all:
>>
>> Im having a little bit confuse of passing a pointer variable to a
>> function that accept reference:
>>
>> void test(int &temp)
>> {
>>
>> temp+= temp + 2;
>>
>> cout << "function:" << temp << endl;
>> cout << "function:" << &temp << endl; //c:0x22ff1c
>> }
>>
>> int main(int argc, char *argv[])
>> {
>>
>> int c = 0;
>> int *d = &c;
>> cout << "d:" << *d << endl;
>> test(*d); // i guess, *d is dereference of d, which is value of c,
>> and same as int &temp = c, like passing reference?
>> cout << "c:" << &c << endl; //function:0x22ff1c,
>> return 0;
>> }
>>
>> it works, i guess, *d is dereference of d, which is value of c, and
>> same as int &temp = c, like passing reference?
>>
>
>
> Perhaps you could get a hint from the character used to denote a
> reference: &
>
> When you write: int &temp; temp = c; int x =
> temp;
> what actually happen is like: int * temp; temp = &c; int x =
> *temp;
>
> int x = *temp;
> <=> int x = *&c; // since temp = &c
> <=> int x = c; // since *& = identity.
>
> You may consider the reference variables as pointers that are
> automatically deferenced everytime they're used.
>
>
>> In the above code i'm trying to pass a dereference pointer d, which is
>> contain value of c, can anyone can explain to me if this is a good way
>> to pass a pointer variable?
>
> You didn't pass a pointer, you passed an int.
> To pass a pointer you'd have to use the *.
>
>
> void take_a_raw_pointer (int* param){
> (*param)=42; // modifies the int pointed to by param.
> param=0; // modifies param.
> }
>
> void take_a_pointer_reference(int*& param){
> (*param)=42; // modifies the int pointed to by the pointer referenced
> by param.
> param=0; // modifies the pointer referenced by param.
> }
>
> /*
> The difference is that take_a_raw_pointer will accept temporary
> pointers returned by functions, while take_a_pointer_reference will
> want a pointer variable.
> */
>
> int* p=&c;
> int* compute_some_int_pointer();
>
> take_a_raw_pointer(&c);
> take_a_raw_pointer(p); // p cannot be modified assert(p==&c);
> take_a_raw_pointer(compute_some_int_pointer());
>
> take_a_pointer_reference(p); // p might be modified and be null or point
> to another int than c.
>
>
> --
> __Pascal Bourguignon__

== 2 of 2 ==
Date: Tues, Sep 29 2009 7:20 pm
From: "Louis"


Hi Michael:

1. test is a void function accepting an int lvalue
2. c is passed into test

Is that means i'm passing an int c, and temp is reference to c , eq int
&temp = c.

Let say for some reason, i must use pointer in main
int *ptr = new int(10);

and another function must accept an reference like void test(int &temp)

so passing ptr to test by using

test(*ptr);

will result passing as reference? is there any better way to do it? or this
is normal?

Many Thanks
L

"Michael Tsang" <miklcct@gmail.com> wrote in message
news:h9sh9a$1f7$1@news.eternal-september.org...
> Louis wrote:
>
>> Hi all:
>>
>> Im having a little bit confuse of passing a pointer variable to a
>> function
>> that accept reference:
>>
>> void test(int &temp)
> test is a void function accepting an int lvalue
>> {
>>
>> temp+= temp + 2;
>>
>> cout << "function:" << temp << endl;
>> cout << "function:" << &temp << endl; //c:0x22ff1c
>> }
>>
>> int main(int argc, char *argv[])
>> {
>>
>> int c = 0;
>> int *d = &c;
>> cout << "d:" << *d << endl;
> *d is an int lvalue which is the same object as c
>> test(*d); // i guess, *d is dereference of d, which is value of c,
> c is passed into test
>> and
>> same as int &temp = c, like passing reference?
>> cout << "c:" << &c << endl; //function:0x22ff1c,
>> return 0;
>> }
>>
>> it works, i guess, *d is dereference of d, which is value of c, and same
>> as int &temp = c, like passing reference?
>>
>> In the above code i'm trying to pass a dereference pointer d, which is
>> contain value of c, can anyone can explain to me if this is a good way to
>> pass a pointer variable?
>>
>> Many Thanks
>>
>> L
>


==============================================================================
TOPIC: problem with template
http://groups.google.com/group/comp.lang.c++/t/3794de606deb5029?hl=en
==============================================================================

== 1 of 1 ==
Date: Tues, Sep 29 2009 7:07 pm
From: "Eric Pruneau"

"bite" <anonimo.passante@gmail.com> a écrit dans le message de news:
a6f1c66d-5a5f-4670-a61d-9604780df0c3@d10g2000yqh.googlegroups.com...
On 29 Set, 18:45, Noah Roberts <d...@reply.com> wrote:
> In article <c4e7b0bc-472b-4e44-989a-6e19b328bed6
> @m38g2000yqd.googlegroups.com>, anonimo.passa...@gmail.com says...
>
>
>
>
>
> > Anybody could tell me what is wrong with these few lines of code?
>
> > #include <map>
> > #include <vector>
>
> > template<class Key, class Value>
> > #include <map>
> > #include <vector>
>
> > template<class Key, class Value>
> > class PointerVector : public std::vector<Value *>
> > {
> > public:
> > PointerVector () {}
> > PointerVector (std::map<Key, Value> & as) : std::vector<Value *>
> > (as.size ())
> > {
> > int i = 0;
> > std::map<Key, Value>::iterator it;
>
> prefix the above line with "typename".
>

Wonderful, thank you very much.

Now I'll try to learn what 'typename' is :)

It is to clarify that an identifier inside a template is a type.


Eric Pruneau


==============================================================================

You received this message because you are subscribed to the Google Groups "comp.lang.c++"
group.

To post to this group, visit http://groups.google.com/group/comp.lang.c++?hl=en

To unsubscribe from this group, send email to comp.lang.c+++unsubscribe@googlegroups.com

To change the way you get mail from this group, visit:
http://groups.google.com/group/comp.lang.c++/subscribe?hl=en

To report abuse, send email explaining the problem to abuse@googlegroups.com

==============================================================================
Google Groups: http://groups.google.com/?hl=en

No comments: