Miranda functions and Initialization

Discussion in 'C++' started by JKop, Aug 1, 2004.

  1. JKop

    JKop Guest

    Is this them all?:


    class Dummy
    {
    public:

    Dummy() {}

    Dummy(const Dummy& original) { }

    Dummy& operator=(const Dummy& lhs) {}

    const Dummy * operator&() const { return this; }

    Dummy * operator&() { return this; }

    ~Dummy() {}

    };


    Also could anyone please inform me of circumstances in which these are
    edited and in which they disappear? For example I'm already aware of the
    following:

    1) Dummy() disappears if you supply another one that takes arguments, eg.
    Dummy(int).

    2) operator= and the copy constructor will change for every extra member
    variable that's added to the class.


    --

    Now, take the following:

    int main()
    {
    int j;
    }


    I'm fully aware that j contains no particular value, it hasn't been
    initialized.

    Now take the following:

    int main()
    {
    int j = 45;
    }

    I'm fully aware that that's equal to:

    int j = int(45);

    But, where you have user-defined types, what exactly goes on?

    For instance:

    SomeClass k = 78.222;


    Does that become:

    SomeClass k = SomeClass(78.222);

    And then is the SomeClass(const SomeClass&) copy constructor called? Or...
    does the compiler simply look for a different copy constructor, eg.
    SomeClass(const double&)? Or is that even valid?

    Anyway here's what I'm getting at: I know int() is equal to zero, ie. if you
    specify brackets then it gets intialized to zero. Now ofcourse you have the
    problem of:

    int main()
    {
    int j();
    }

    The compiler doesn't know if it's an object definition or a function
    declaration (...if only "extern" was compulsory). As such, it assumes a
    function declaration.

    Is the only way to get around this to write:

    int j(0);

    ?

    Anyway here comes my question:

    class Chocolate
    {
    public:

    int a;

    double b;

    };


    int main()
    {
    Chocolate choco;
    }


    Do "a" and "b" get initialized to zero? And if so, what does it? Is it the
    miranda default constructor? What about in the following code:

    class Chocolate
    {
    public:

    int a;

    double b;

    Chocolate() {}

    };


    int main()
    {
    Chocolate choco;
    }


    Do "a" and "b" get initialized to zero in the above?


    -JKop
     
    JKop, Aug 1, 2004
    #1
    1. Advertisements

  2. No, the compiler generated default ctor leaves scalar types uninitalised.
    Again no. The default ctor you wrote is identical to the compiler
    generated default ctor, it leaves a and b uninitialised.

    You can write this

    Chocolate choco = Chocolate();

    which would zero initalise a and b in the first definition of Chocolate
    you gave but not in the second. Chocolate() is value initialsation which
    differs from default initialisation in that it zero initialises scalar
    types in a class without a user declared ctor.

    john
     
    John Harrison, Aug 1, 2004
    #2
    1. Advertisements

  3. JKop

    Rolf Magnus Guest

    The compiler won't generate a default constructor for you if you write a
    user defined one, if that's what you mean.
    They just do a memberwise copy. So yes, you could say that they change
    when you add members to your class.
    That's not a copy constructor, but a conversion constructor. And yes,
    that one is needed, two. First, a nameless temporary object of class
    SomeClass is created using that constructor, then k is copy-constucted
    from that one. Note however, that the C++ standard gives explicit
    permission to directly create k from the double value, omiting the
    temporary, but even if the copy constructor is never called, it still
    has to be available. If, however, you write:

    SomeClass k(78.222);

    only the conversion constructor from double is needed and the copy
    constructor is not involved.
    Yes. This constructor-style initialization can come in handy in
    templates.
    Well, the above _is_ a function declaration.
    No. You can do:

    int j = int();

    But usually, I'd just write the more intuitive:

    int j = 0;
    No. They stay uninitialized.
    It's the (empty) compiler-generated default constructor.
    You didn't write any code to initialze a or b, so they don't get
    initialized.
     
    Rolf Magnus, Aug 1, 2004
    #3
  4. JKop

    JKop Guest

    #include <string>

    class Cheese
    {
    public:

    int a;
    double b;
    std::string name;
    };


    int main()
    {
    Cheese mouse;
    }


    So in the above, "a" and "b" contain white noise, while "name" has been
    constructed properly.

    Is there any way I can turn the function declaration into an object
    definition?!

    I see that I can do:

    Cheese mouse = Cheese();

    Is that the *only* way?

    So anyway...

    I see in a lot of Win32 documentation that when they have a structure that's
    to be passed to a Win32 function, like:

    struct SETTINGS
    {
    int AMOUNT_PORTS;
    bool ANY_OPEN;
    unsigned char* SET_ID;
    };


    that in the code they have:


    SETTINGS sets;
    memset(&sets,0,sizeof(sets));

    So instead of that can one write:

    SETTINGS sets = SETTINGS();

    Another thing with my way, any pointer variables are given they're proper
    null pointer value, as opposed to just 0.


    BTW, I've also just noticed lately that you can do the following:

    extern void Blah(unsigned long);
    extern void Blah(unsigned);
    extern void Blah(unsigned short);

    int main()
    {
    Blah(unsigned short(52U));
    }


    Happy Days!


    -JKop
     
    JKop, Aug 1, 2004
    #4
  5. JKop

    JKop Guest

    In the following, are "Dummy" and "DummyClone" identical?

    #include <string>

    class Dummy
    {
    private:

    int a;

    protected:

    std::string name;

    public:

    double k;
    };


    class DummyClone
    {
    private:

    int a;

    protected:

    std::string name;

    public:

    double k;

    public:

    DummyClone() {}

    DummyClone* operator&() { return this; }
    const DummyClone* operator&() const { return this; }

    DummyClone(const DummyClone& original)
    {
    a = original.a;
    name = original.name;
    k = original.k;
    }

    DummyClone& operator=(const DummyClone& lhs)
    {
    a = lhs.a;
    name = lhs.name;
    k = lhs.k;
    }

    ~DummyClone() { }
    };


    int main()
    {
    Dummy x;

    DummyClone y;

    }


    Have I left out any miranda functions? Are there 6 in all?

    -JKop
     
    JKop, Aug 1, 2004
    #5
  6. * JKop:
    In theory yes, in practice no, because many compilers do not respect
    the standard in this regard.

    Instead write


    SETTINGS sets = {0};


    Often the following idiom is useful:


    SOME_MS_UPPERCASE_TYPE ugh = {sizeof(ugh)};
    STATIC_ASSERT( offsetof( SOME_MS_UPPERCASE_TYPE, hnSize ) == 0 );


    You can find a nice implementation of STATIC_ASSERT in e.g. the
    0 is the null value for pointers.
     
    Alf P. Steinbach, Aug 1, 2004
    #6
  7. JKop

    David Hilsee Guest

    I think he's talking about the difference between "all bits zero" and a null
    pointer. While the literal zero can be used to signify a null pointer, that
    doesn't mean that a null pointer must have a representation where all of its
    bits are zero.
     
    David Hilsee, Aug 1, 2004
    #7
  8. JKop

    JKop Guest

    Alf P. Steinbach posted:
    Please explain what you mean - are you saying that not
    many compilers will compile the above as specified by the
    Standard?
    Not necessarily. And the Standard provides for this. Where
    you write:

    int* k = 0;

    It replaces 0 with the appropriate null pointer value.

    But when you use memset, there's no replacement.

    -JKop
     
    JKop, Aug 1, 2004
    #8
  9. * JKop:
    Yes.
     
    Alf P. Steinbach, Aug 1, 2004
    #9
  10. JKop

    Rolf Magnus Guest

    The compiler generated copy constructor will do a memberwise copy
    initializiation, while you do a default (or in the case of built-in
    types no) initialization, followed by an assignment. This makes a
    difference for the std::string member, which first gets
    default-construted and then assigned, instead of copy-constructed. A
    copy constructor that does the same as the compiler generated one would
    do looks like this:

    DummyClone(const DummyClone& original)
    : a(original.a),
    name(original.name),
    k(original.k)
    {
    }
    --
    Kyle: "Hey, Stan, now that Terrance & Phillip has been taken off the
    air, what
    are we gonna do for entertainment?"
    Stan: "I don't know. We, we could start breathing gas fumes."
    Cartman: "My uncle says that smoking crack is kinda cool"
    Kyle: "Hey, why don't we watch some of those porno movie thingies?"
     
    Rolf Magnus, Aug 1, 2004
    #10
  11. JKop

    JKop Guest

    What do they do instead?

    In the absence of optimization, here's what should happen:

    1) A SETTINGS object is created, all values intialized to 0.
    2) sets is copy-constructed from the previous object.
    3) The original object is destroyed.

    And with optimization:

    1) sets is created, all values initialized to 0.


    Where do these other alleged C++ compilers go wayward?


    -JKop
     
    JKop, Aug 1, 2004
    #11
  12. JKop

    JKop Guest

    Thanks Rolf.

    So now we have:

    #include <string>

    class Dummy
    {
    private:

    int a;

    protected:

    std::string name;

    public:

    double k;
    };


    class DummyClone
    {
    private:

    int a;

    protected:

    std::string name;

    public:

    double k;

    public:

    DummyClone() {}

    DummyClone* operator&() { return this; }
    const DummyClone* operator&() const { return this; }

    DummyClone(const DummyClone& original)
    : a(original.a), name(original.name), k(original.k) {}

    DummyClone& operator=(const DummyClone& lhs)
    {
    a = lhs.a;
    name = lhs.name;
    k = lhs.k;
    }

    ~DummyClone() { }
    };


    int main()
    {
    Dummy x;

    DummyClone y;
    }


    Is that it now?


    -JKop
     
    JKop, Aug 1, 2004
    #12
  13. * JKop:
    According to my notes Visual C++ 7.0 is one such alleged compiler... ;-)

    Visual C++ 7.1 seems to do it right.
     
    Alf P. Steinbach, Aug 1, 2004
    #13
  14. Dummy and DummyClone still differ if value initialised

    Dummy* d = new Dummy();
    DummyClone* dc = new DummyClone();

    Here d->a and d->k are guaranteed to be zero (assuming you have a compiler
    which implements value initialisation correctly) but dc->a and dc->k are
    uninitialised.

    john
     
    John Harrison, Aug 2, 2004
    #14
  15. I think many would fail to iniitalise to zero. As I understand it this was
    acceptable pre-2003 standard.

    john
     
    John Harrison, Aug 2, 2004
    #15
  16. JKop

    JKop Guest

    Dummy and DummyClone still differ if value initialised

    And there's no way around this?

    Also I presume that if you leave it like:

    Dummy* d = new Dummy;

    the it contains white noise, yes?

    Now here's a tricky one:

    A class that has only public data, but it has a contructor:

    class Chunky
    {
    public:
    int a;
    double b;
    char c;

    Chunky() {}
    };


    If I do:

    Chunky chunks;

    Then "a", "b" and "c" contain white noise. That right?

    While if I do:

    Chunky chunks = Chunky();

    Then it still contains white noise (on account of the constructor). That
    right?

    What I'm getting at is if a certain class has a contructor, are:

    Chunk chunks;
    Chunky chunks = Chunky();

    identical, in that they both contain white noise?


    -JKop
     
    JKop, Aug 2, 2004
    #16
  17. I don't think so.
    Right, value initialisation only makes a difference (as far as I can tell)
    for types without a constructor.
    It depends on the default constuctors of course, but otherwise both are
    identical.

    john
     
    John Harrison, Aug 2, 2004
    #17
  18. JKop

    JKop Guest

    Which leads me on to POD types.

    For instance, take the following:

    #include <string>

    class Cow
    {
    public:
    int a;
    double b;
    std::string c;
    };

    int main
    {
    Cow dairy_cow = { 5, 67.2, std::string("Moo!") };
    }


    It looks like a type is no longer a POD when the above syntax in "main" is
    no longer valid. For instance, take:


    class Cow
    {
    public:
    int a;
    double b;
    std::string c;

    private:

    char t;
    };

    int main
    {
    Cow dairy_cow = { 5, 67.2, std::string("Moo!") };
    }


    Now the compiler is telling me that a "Cow" can't be defined like that, and
    that you've to use a constructor.

    I've found the following things render a class no longer a POD:

    a) Putting in private or protected member data
    b) Putting in a constructor or copy-constructor

    And that the following are no problem, it's still a POD:

    a) Putting in member functions
    b) Putting in operator member functions
    (even if they're private or protected)


    It's good to know this stuff!

    So now I think I fully understand all the initialization stuff in C++.


    There's just one thing that I want to figure out:

    SomeClass object = SomeClass();


    There has to be some sort of way of turning the following:

    SomeClass object();

    into an object definition. I've tried:

    class SomeClass object();
    struct SomeClass object();

    But still they're a function declaration. That doesn't make sense to me.
    It'd even be compatible with C, because while you would prefix "struct" in
    C, you still wouldn't put in parenthesis. And there was no "class" in C
    either.

    Anyone know how to tell the compiler it's an object definition?


    -JKop
     
    JKop, Aug 2, 2004
    #18
  19. JKop

    Old Wolf Guest

    [some stuff snipped from these definitions]
    No. DummyClone contains operator& and Dummy does not. You also made
    this mistake in your original post.
    You included too many. Don't be misled by mistakes in the book
    'C++ by Dummies' (which also invented the term 'miranda functions').

    If you don't believe it, add these lines to main:

    & DummyClone::eek:perator &;
    & Dummy::eek:perator &;

    and note the compiler error.
     
    Old Wolf, Aug 3, 2004
    #19
  20. JKop

    JKop Guest

    Old Wolf posted:
    Although the following *does* compile:

    class Dummy {};

    void Blah(Dummy* a) {}
    void Blah(const Dummy*) {}

    int main()
    {
    Dummy k = Dummy();
    const Dummy j = Dummy();

    Blah(&k);
    Blah(&j);
    }


    -JKop
     
    JKop, Aug 3, 2004
    #20
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.