what's the difference between value-initialization and default-initialization?

Discussion in 'C++' started by Jess, Apr 25, 2007.

  1. Jess

    Jess Guest

    Hello,

    I understand the default-initialization happens if we don't initialize
    an object explicitly. I think for an object of a class type, the
    value is determined by the constructor, and for the built-in types,
    the value is usually garbage. Is this right?

    However, I'm a bit confused about value-initialization, when does it
    happen, and what kind of values are assigned to objects?

    Thanks.
    Jess, Apr 25, 2007
    #1
    1. Advertising

  2. Jess wrote:
    > Hello,
    >
    > I understand the default-initialization happens if we don't initialize
    > an object explicitly. I think for an object of a class type, the
    > value is determined by the constructor, and for the built-in types,


    Not only built-in types but POD (plain old data) types.

    > the value is usually garbage. Is this right?


    Yes, unless you use a () in your initialization of the POD members/data.

    >
    > However, I'm a bit confused about value-initialization, when does it
    > happen, and what kind of values are assigned to objects?


    You assign whatever value type you enable. Usually, a class has a copy
    constructor and an assignment operator available.

    i.e.

    struct Z
    {
    Z() {} // YYY
    Z( const char * ) {}
    Z & operator=( const char * ) {} // XXX
    };

    Z x( "HI" );

    Z y( x ); // copy constructor (compiler provided YYY)

    int main()
    {

    y = x; // assignment operator (compiler provided)

    y = "THERE"; // assignment operator XXX

    }
    Gianni Mariani, Apr 25, 2007
    #2
    1. Advertising

  3. Jess

    Jess Guest

    > Not only built-in types but POD (plain old data) types.

    What is POD?

    > Yes, unless you use a () in your initialization of the POD members/data.

    Again, could you please give more explanation?

    > You assign whatever value type you enable. Usually, a class has a copy
    > constructor and an assignment operator available.
    >
    > i.e.
    >
    > struct Z
    > {
    > Z() {} // YYY
    > Z( const char * ) {}
    > Z & operator=( const char * ) {} // XXX
    >
    > };
    >
    > Z x( "HI" );
    >
    > Z y( x ); // copy constructor (compiler provided YYY)
    >
    > int main()
    > {
    >
    > y = x; // assignment operator (compiler provided)
    >
    > y = "THERE"; // assignment operator XXX
    >
    > }

    It'd be very helpful if you could explain the example. Thanks a lot!
    Jess, Apr 26, 2007
    #3
  4. Jess

    Mumia W. Guest

    On 04/25/2007 12:11 AM, Jess wrote:
    > Hello,
    >
    > I understand the default-initialization happens if we don't initialize
    > an object explicitly. I think for an object of a class type, the
    > value is determined by the constructor, and for the built-in types,
    > the value is usually garbage. Is this right?
    >
    > However, I'm a bit confused about value-initialization, when does it
    > happen, and what kind of values are assigned to objects?
    >
    > Thanks.
    >



    #include <cstdio>
    #include <cstdlib>

    class Foo {
    public:
    int value;
    const char * str;

    void print (FILE * fh) {
    fprintf(fh, "%d => %s\n", value, str);
    }
    };

    int main ()
    {
    Foo myfoo = { 10, "Hello" };
    myfoo.print(stdout);

    return EXIT_SUCCESS;
    }

    -----end-code--------

    Notice that myfoo was initialized by values written in the style used to
    initialize POD (plain old data--known in C as 'structs').
    Mumia W., Apr 26, 2007
    #4
  5. Jess wrote:
    > > Not only built-in types but POD (plain old data) types.

    >
    > What is POD?


    Google "POD (plain old data)" - here is an "I'm Feeling Lucky Link"

    http://www.google.com/search?hl=en&q=POD Plain Old Data&btnG=Google Search

    >
    >> Yes, unless you use a () in your initialization of the POD members/data.

    > Again, could you please give more explanation?



    Consider this:

    struct A { int x; A() : x() {} };

    struct B { int x; };

    int main()
    {
    A a;
    B b;

    return a.x == b.x;
    }

    The value of a.x is always 0. The value of b.x is indeterminate or
    uninitialized.

    This applies for all POD types.

    B is a POD type;

    consider:
    B b( B() );

    .... b.x is now initialized.

    Note that if you had written:
    B b(); // function declaration of function b() returning a B.
    .... nasty little issue for newbies...


    >
    >> You assign whatever value type you enable. Usually, a class has a copy
    >> constructor and an assignment operator available.
    >>
    >> i.e.
    >>
    >> struct Z
    >> {
    >> Z() {} // YYY
    >> Z( const char * ) {}
    >> Z & operator=( const char * ) {} // XXX
    >>
    >> };
    >>
    >> Z x( "HI" );
    >>
    >> Z y( x ); // copy constructor (compiler provided YYY)
    >>
    >> int main()
    >> {
    >>
    >> y = x; // assignment operator (compiler provided)
    >>
    >> y = "THERE"; // assignment operator XXX
    >>
    >> }

    > It'd be very helpful if you could explain the example. Thanks a lot!


    You need to read the chapter on constructors in C++ in your favorite
    book and come back.
    Gianni Mariani, Apr 26, 2007
    #5
  6. Jess

    James Kanze Guest

    On Apr 25, 7:11 am, Jess <> wrote:

    > I understand the default-initialization happens if we don't initialize
    > an object explicitly. I think for an object of a class type, the
    > value is determined by the constructor, and for the built-in types,
    > the value is usually garbage. Is this right?


    Written with a hyphen, no. "default-initialization" is a
    technical term, defined and used in the standard:

    To default-initialize an object of type T means:

    -- if T is a non-POD class type (clause 9), the default
    constructor for T is called (and the initialization
    is ill-formed if T has no accessible default
    constructor);

    -- if T is an array type, each element is
    default-initialized;

    -- otherwise, the object is zero-initialized.

    Note, however, that variables aren't default-initialized by
    default:).

    > However, I'm a bit confused about value-initialization, when
    > does it happen, and what kind of values are assigned to
    > objects?


    Again, a technical term used in the standard (or at least the
    latest draft). I'll admit that when reading the standard, I
    can't quite make out what the intended difference between
    default initialization and value initialization is supposed to
    be. The original version (ISO 14882:1998) doesn't have value
    initialization.

    I suspect that the intent is to ensure that zero initialization
    occurs when the type has a non trivial implicit constructor.
    The exact wording is:

    To value-initialize an object of type T means:

    -- if T is a class type (clause 9) with a user-declared
    constructor (12.1), then the default constructor for
    T is called (and the initialization is ill-formed if
    T has no accessible default constructor);

    -- if T is a non-union class type without a
    user-declared constructor, then every non-static
    data member and baseclass component of T is
    value-initialized;

    -- if T is an array type, then each element is
    value-initialized;

    -- otherwise, the object is zero-initialized

    Basically, what gets added is the second point. If I have a
    class something like:

    class C
    {
    public:
    virtual ~C() {}
    int x ;
    } ;

    It's not a POD, but it doesn't have a user defined
    constructor, so value-initialization guarantees that x is
    set to 0, whereas default-initialization doesn't.

    And to quote the standard: "An object whose initializer is
    an empty set of parentheses, i.e. () shall be
    value-initialized." (In the latest draft;
    default-initialized in the 1998 version of the standard.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Apr 26, 2007
    #6
  7. Jess

    Ron Natalie Guest

    James Kanze wrote:

    >
    > Note, however, that variables aren't default-initialized by
    > default:).


    One of the most stupid features of C++. Variables aren't always
    default-initialized.

    >
    > I suspect that the intent is to ensure that zero initialization
    > occurs when the type has a non trivial implicit constructor.
    > The exact wording is:
    >

    Well, more specifically, it makes the behavior consistent when
    the object contains objects of possibly non-POD type. Before
    this concept was defined you couldn't figure out how:

    struct S {
    int i;
    T t;
    } s;

    would be initialized unless you knew what T was.
    Ron Natalie, Apr 26, 2007
    #7
  8. Jess

    Jess Guest

    On Apr 26, 7:13 pm, Gianni Mariani <> wrote:
    > struct A { int x; A() : x() {} };
    >
    > struct B { int x; };
    >
    > int main()
    > {
    > A a;
    > B b;
    >
    > return a.x == b.x;
    >
    > }
    >
    > The value of a.x is always 0. The value of b.x is indeterminate or
    > uninitialized.


    This is called default-initialization, right?

    > consider:
    > B b( B() );
    >
    > ... b.x is now initialized.


    I don't quite understand this... "B()" creates a temporary object and
    it's passed to a copy-constructor to initialize "b", and the copy
    constructor tries to copy "x" value of the tmp object to "b"'s "x".
    However, what is the value of tmp object's "x"?

    > You need to read the chapter on constructors in C++ in your favorite
    > book and come back.


    I did read Accelerated C++, but am still confused. In order to
    clarify the matter, here's what I think, not sure whether they are
    right/wrong:

    1. Default initialization is used when we create an object using the
    form "T t", where T can be a POD type or class type. If this happens,
    the following occurs:
    a. if T is POD, then "t" is garbage value
    b. if T is class, then it's default constructor is invoked. If
    there's no default contructor, the compiler will synthesize one.
    (i). If there's a default constructor, then all T's POD member data is
    initialized according to the constructor initializer list; any POD
    member not mentioned in the initializer list gets default-init, with
    garbage value. If T has a class-typed member (say of type A), then
    A's default constructor is called and if A has no default constructor,
    then the synthesized constructor will be called. FInally, the
    constructor's body is entered.
    (ii). If there is no default constructor, then the synthesized
    constructor will be called. All POD member gets garbage data and
    class members have their default constructor (or synthesized default
    constructors) invoked.

    Is this what happens to default-init? Moreover, to init POD member in
    the constructor initializer, I can do things like "x(10)" and also
    "x()" where "x" is an int, is this right? If "x()" is used, then "x"
    gets value-init to 0?

    2. Value-initialization happens if a constructor is explicitly invoked
    like "T t(arg)", or when we invoke copy constructor. For a class type
    object:
    a. if it's created by invoking a constructor like "T t(arg)", then all
    its POD member gets initialized according to the constructor
    initializer; any POD member not mentioned gets value-init to 0. But
    what happens to those class-typed members? Are their default
    constructors (or synthesized one) called? I think after all these are
    done, the constructor's body is entered.
    b. if the T object is created through copy constructor, then the
    values of the existing objects are copied into the new object.
    However, what if we have an example like "B b(B())"? what's the value
    of the tmp object?

    3. To value-init a POD object, I think the only way is to do something
    like:

    int n = int();
    is this right?

    4. The book Accelerated C++ also says that if an object is used to
    init a container element, either as a side effect of adding new
    element to a "map", or as the elements of a container defined to have
    a given size, then the members will be value-initialized. I checked
    it through an example,

    struct A{
    int x;
    };

    int main(){
    A a[10];
    return 0;
    };

    Then I found out each element in a has it's "x" value as 0. I think
    this is what the author of the book meant. Then I tried another
    example:

    int main(){
    int b[10];
    return 0;
    }

    This time, each element in b has garbage value. Isn't each member of
    b supposed to be value-init to 0?

    I'd really appreciate it if some of you could answer my questions and
    point out my mistakes and also let me know the points I overlooked.
    Thanks.
    Jess
    Jess, Apr 29, 2007
    #8
  9. Jess wrote:
    > On Apr 26, 7:13 pm, Gianni Mariani <> wrote:
    >> consider:
    >> B b( B() );
    >>
    >> ... b.x is now initialized.

    >
    > I don't quite understand this... "B()" creates a temporary object [..]


    B b(B());

    is a declaration of a funciton. There is no b.x. 'b' is a function.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Apr 29, 2007
    #9
  10. Jess

    Jess Guest

    On Apr 30, 2:13 am, "Victor Bazarov" <> wrote:
    > B b(B());
    >
    > is a declaration of a funciton. There is no b.x. 'b' is a function.


    But in your previous message, you mentioned "b.x" is initialized?
    Also, "B()" calls B's default constructor, and the result is a B
    object. When we use this temporary object to "B b(B())", aren't we
    calling the copy-constructor?

    Thanks
    Jess
    Jess, May 1, 2007
    #10
  11. Jess

    Ron Natalie Guest

    Jess wrote:
    > On Apr 30, 2:13 am, "Victor Bazarov" <> wrote:
    >> B b(B());
    >>
    >> is a declaration of a funciton. There is no b.x. 'b' is a function.

    >
    > But in your previous message, you mentioned "b.x" is initialized?
    > Also, "B()" calls B's default constructor, and the result is a B
    > object. When we use this temporary object to "B b(B())", aren't we
    > calling the copy-constructor?
    >


    You can't call constructors, constructors are called by object creation.
    The above is not an object creation. It's a definition of a function
    called "b' which takes a paramter of type B and returns B.
    Ron Natalie, May 1, 2007
    #11
  12. * Ron Natalie:
    > Jess wrote:
    >> On Apr 30, 2:13 am, "Victor Bazarov" <> wrote:
    >>> B b(B());
    >>>
    >>> is a declaration of a funciton. There is no b.x. 'b' is a function.

    >>
    >> But in your previous message, you mentioned "b.x" is initialized?
    >> Also, "B()" calls B's default constructor, and the result is a B
    >> object. When we use this temporary object to "B b(B())", aren't we
    >> calling the copy-constructor?
    >>

    >
    > You can't call constructors, constructors are called by object creation.


    Sort of. You might argue that that statement is purely about
    terminology. But even so, the standard uses the terms "call" and
    "invoke", the language's creator does so, I do so, and in short, the
    statement is just plain wrong no matter whether it's about what one can
    do or about established terminology.

    An accurate statement is that outside a constructor initializer list you
    can't call a constructor on existing storage, except by using low-level
    (not type safe) shenanigans[1].

    A more useful but not quite as accurate statement is that with at least
    one user-defined constructor C++ effectively provides a construction
    guarantee where each object (including each sub-object) receives exactly
    one constructor call, which happens before anything else.


    > The above is not an object creation. It's a definition of a function
    > called "b' which takes a paramter of type B and returns B.


    Right.

    And the reason has nothing to do with constructor calls, but with an
    ambiguity in the grammar, which the standard requires is always resolved
    in favor of a function declaration, if possible.

    By including additional parentheses an interpretation as a function
    declaration is no longer possible,

    B b((B()));

    but there's a limit to how subtle code one should write, so it's better
    to do the straightforward

    B b;

    or, in some contexts,

    B b = B();

    Cheers,

    - Alf


    Notes:
    [1] Low-level shenanigans include in-place construction.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, May 1, 2007
    #12
  13. Jess

    Old Wolf Guest

    On May 1, 11:40 pm, "Alf P. Steinbach" <> wrote:
    > but there's a limit to how subtle code one should write, so it's better
    > to do the straightforward
    >
    > B b;
    >
    > or, in some contexts,
    >
    > B b = B();


    Doesn't the latter require an accessible copy constructor?
    Old Wolf, May 1, 2007
    #13
  14. Jess

    Jess Guest

    On 5ÔÂ1ÈÕ, ÏÂÎç9ʱ40·Ö, "Alf P. Steinbach" <> wrote:
    > > The above is not an object creation. It's a definition of a function
    > > called "b' which takes a paramter of type B and returns B.

    >
    > Right.


    So "B b(B());" is a definition of "b"? Then it's return type is "B"
    and its argument type "looks like" B to me. I'm saying it "looks
    like" "B" because it's paramenter is "B()" instead of the standard
    format like "type arg". Moreover, if this is a definition of "b",
    then why can I receive a B object after this execution, where's the
    invocation of the function "b"?

    > but there's a limit to how subtle code one should write, so it's better
    > to do the straightforward
    >
    > B b;
    >
    > or, in some contexts,
    >
    > B b = B();


    I think the default constructor is called in the first case. For the
    second case, a default constructor is called for "B()", then a copy-
    constructor is called (by the compiler) to copy the "B" to a temporary
    result, and then another copy-constructor is called to copy the
    temporary B object to "b" to initialize "b", is this right? In terms
    of value-initialization and default-initialization, are these two
    examples the same? I think the first one looks like default-init and
    the second one looks like value-init. I'm still not quite sure about
    the differences.

    Could someone answer my questions that I posed earlier and point out
    whether I've made mistakes about value- and defaul-initialization? :)
    Perhaps I should start a new thread in case it's not obvious what my
    questions are. :)
    Jess, May 2, 2007
    #14
  15. Jess

    Old Wolf Guest

    On May 2, 11:51 am, Jess <> wrote:
    > On 5ÔÂ1ÈÕ, ÏÂÎç9ʱ40·Ö, "Alf P. Steinbach" <> wrote:
    >
    > > > The above is not an object creation. It's a definition of a function
    > > > called "b' which takes a paramter of type B and returns B.

    >
    > > Right.


    Must have been a long day for Ron and Alf. The parameter to 'b'
    has type 'pointer to function taking no arguments and returning B'.
    It is the same as:
    B b( B (*)() );

    > So "B b(B());" is a definition of "b"? Then it's return type is "B"
    > and its argument type "looks like" B to me.


    Looks can be deceiving :)

    > I'm saying it "looks like" "B" because it's paramenter is "B()"
    > instead of the standard format like "type arg".


    "type arg" is not a "standard format". Some simple declarations
    look like that, but the syntax for declarations is more complicated,
    with "arg" sometimes coming in between different parts of "type".
    For example, int x[5]

    > Moreover, if this is a definition of "b", then why can I receive a B
    > object after this execution, where's the invocation of the function "b"?


    Huh? (Post some code to illustrate what you mean).

    > > but there's a limit to how subtle code one should write, so it's better
    > > to do the straightforward

    >
    > > B b;

    >
    > > or, in some contexts,

    >
    > > B b = B();

    >
    > I think the default constructor is called in the first case. For the
    > second case, a default constructor is called for "B()", then a copy-
    > constructor is called (by the compiler) to copy the "B" to a temporary
    > result, and then another copy-constructor is called to copy the
    > temporary B object to "b" to initialize "b", is this right?


    You have one step too many (I think). A temporary object is default-
    constructed, and then 'b' is copy-constructed from that object.
    Old Wolf, May 2, 2007
    #15
  16. Jess

    Ron Natalie Guest

    Alf P. Steinbach wrote:

    > Sort of. You might argue that that statement is purely about
    > terminology.


    And the standard has non-ambiguous terminology.

    > But even so, the standard uses the terms "call" and
    > "invoke",


    But doesn't refer to programs being able to call constructors. It
    specifically states to the contrary.

    I don't see why you insist on continually inserting this non-sequitor
    incorrect argument in discussions. It just confuses the issue.

    >
    > An accurate statement is that outside a constructor initializer list you
    > can't call a constructor on existing storage, except by using low-level
    > (not type safe) shenanigans[1].


    You can't even do it inside a constructor initializer list (if you're
    talking about the mem-init list), the belief that such a list is a
    constructor call further confuses the fact that the mem-initializers
    have no bearing at all on constructor invocation order.
    >
    > A more useful but not quite as accurate statement is that with at least
    > one user-defined constructor C++ effectively provides a construction
    > guarantee where each object (including each sub-object) receives exactly
    > one constructor call, which happens before anything else.


    That is correct IF you remove the words user-defined.

    >
    > And the reason has nothing to do with constructor calls, but with an
    > ambiguity in the grammar, which the standard requires is always resolved
    > in favor of a function declaration, if possible.


    Correct, but the original poster thought he was calling a constructor
    which isn't true by either yours or the official standard definition.

    >
    Ron Natalie, May 2, 2007
    #16
  17. Jess

    Jess Guest

    On May 2, 10:30 am, Old Wolf <> wrote:
    > Must have been a long day for Ron and Alf. The parameter to 'b'
    > has type 'pointer to function taking no arguments and returning B'.
    > It is the same as:
    > B b( B (*)() );


    Is it ok to ignore the "*" while still have the same meaning?

    > "type arg" is not a "standard format". Some simple declarations
    > look like that, but the syntax for declarations is more complicated,
    > with "arg" sometimes coming in between different parts of "type".
    > For example, int x[5]


    Indeed, :)

    > > Moreover, if this is a definition of "b", then why can I receive a B
    > > object after this execution, where's the invocation of the function "b"?

    >
    > Huh? (Post some code to illustrate what you mean).


    I made the mistake of thinking this init "b" and realised I was
    wrong....

    > > I think the default constructor is called in the first case. For the
    > > second case, a default constructor is called for "B()", then a copy-
    > > constructor is called (by the compiler) to copy the "B" to a temporary
    > > result, and then another copy-constructor is called to copy the
    > > temporary B object to "b" to initialize "b", is this right?

    >
    > You have one step too many (I think). A temporary object is default-
    > constructed, and then 'b' is copy-constructed from that object.


    I see, so the additional temp object is only created if a function is
    returning, is it right?

    Thanks
    Jess
    Jess, May 2, 2007
    #17
  18. Jess

    Jess Guest

    On May 2, 1:48 pm, Ron Natalie <> wrote:
    > Correct, but the original poster thought he was calling a constructor
    > which isn't true by either yours or the official standard definition.


    I made that mistake because in the constructor initializer, we can do
    something similar:

    struct A{
    int x;
    int y;
    A():x(1),y(){}
    };

    I then thought we can create an A object by "A a()". I get it now.
    thanks!

    Jess
    Jess, May 2, 2007
    #18
  19. * Ron Natalie:
    > Alf P. Steinbach wrote:
    >
    >> Sort of. You might argue that that statement is purely about
    >> terminology.

    >
    > And the standard has non-ambiguous terminology.
    >
    >> But even so, the standard uses the terms "call" and "invoke",

    >
    > But doesn't refer to programs being able to call constructors. It
    > specifically states to the contrary.


    It specifically uses those terms about source code calls in numerous
    places. As far as I know it doesn't state anything to the contrary, and
    that's up at the 99.99% confidence level since this has been discussed
    numerous times, at length. I suggest you look up the most recent thread
    about this in clc++m (James Kanze and me).


    > I don't see why you insist on continually inserting this non-sequitor
    > incorrect argument in discussions. It just confuses the issue.


    Sorry, that's not even wrong.


    >> An accurate statement is that outside a constructor initializer list
    >> you can't call a constructor on existing storage, except by using
    >> low-level (not type safe) shenanigans[1].

    >
    > You can't even do it inside a constructor initializer list (if you're
    > talking about the mem-init list), the belief that such a list is a
    > constructor call further confuses the fact that the mem-initializers
    > have no bearing at all on constructor invocation order.


    Sorry, that's incorrect.


    >> A more useful but not quite as accurate statement is that with at
    >> least one user-defined constructor C++ effectively provides a
    >> construction guarantee where each object (including each sub-object)
    >> receives exactly one constructor call, which happens before anything
    >> else.

    >
    > That is correct IF you remove the words user-defined.


    Sorry that's incorrect. Specifically, without a user-defined constructor,

    B b;

    locally in a function, does not initialize B (another example is use in
    a union).

    The reason the statement is not quite as accurate as the previous one is
    that even with a user defined constructor you can still do e.g.

    B b = b;

    where the compiler is permitted to optimize away the copy constructor
    call; anyway, no real initialization here, but also no low-level things.


    >> And the reason has nothing to do with constructor calls, but with an
    >> ambiguity in the grammar, which the standard requires is always
    >> resolved in favor of a function declaration, if possible.

    >
    > Correct, but the original poster thought he was calling a constructor
    > which isn't true by either yours or the official standard definition.


    Consider the variant with extra parentheses: it's just a syntax issue.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, May 2, 2007
    #19
  20. Jess

    Ron Natalie Guest

    Alf P. Steinbach wrote:

    >
    > Sorry that's incorrect. Specifically, without a user-defined constructor,
    >
    > B b;
    >
    > locally in a function, does not initialize B (another example is use in
    > a union).
    >

    There is an implicitly defined consturctor (admittedly rarely actually
    causing executable code), but it depends on what the definition of B
    is. This is actually the who reason the term "value initialized" was
    invented.
    Ron Natalie, May 2, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jakk
    Replies:
    4
    Views:
    12,049
  2. Gianni Mariani
    Replies:
    4
    Views:
    622
    Gianni Mariani
    Dec 7, 2003
  3. JKop
    Replies:
    10
    Views:
    926
  4. , India
    Replies:
    5
    Views:
    395
    James Kanze
    Aug 21, 2009
  5. Taras_96
    Replies:
    3
    Views:
    573
    Michael Tsang
    Oct 30, 2009
Loading...

Share This Page