2

I am fairly new to C++, have written a sample code:

#include <iostream>

class Point
{  
public:
    int X, Y;

    int dis()
    {
        std::cout << X << Y << std::endl;
        return X;
    }

    int operator=(const Point&)
    { 
        int dat = 3;
        return dat;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{ 
    Point p2 = Point();
    p2.dis();
    return 0;
}

Here p2 should initialize both class Point variables x and y to zero right? But instead when I do p2.dis(), I am getting x and y intialized to some random values.

and in the following case tSum = 0, even if "T" is of type class.

template<typename T>
double GetAverage(T tArray[], int nElements)
{
    T tSum = T(); // tSum = 0
    for (int nIndex = 0; nIndex < nElements; ++nIndex)
    {
        tSum += tArray[nIndex];
    }

    // Whatever type of T is, convert to double
    return double(tSum) / nElements;
}

how is this different ?

Thanks in advance for the clarification.

M.M
  • 138,810
  • 21
  • 208
  • 365
rahul
  • 403
  • 3
  • 6
  • 15
  • Where do templates come in play? You never use `Item`. As stated, the code should work as you describe it. – Luchian Grigore Nov 12 '14 at 21:21
  • You could use **in class initializers** to make your code more readable. Then if the value is not the one you set, you'd only have to search for the place where the defaults are overriden – Lorah Attkins Nov 12 '14 at 21:22
  • 1
    VC++ has some bugs related to value-initialization. – T.C. Nov 12 '14 at 21:22
  • sorry, not using template class at the moment. But I have this issue before I reach to that step. Here I expect p2.dis() to output X=0 and Y=0, but instead it is outputting X=-858993460 and Y=-858993460 – rahul Nov 12 '14 at 21:24
  • possible duplicate of [Variable initialization in C++](http://stackoverflow.com/questions/2218254/variable-initialization-in-c) – BlamKiwi Nov 12 '14 at 21:37
  • @MorphingDragon that's substantially different – M.M Nov 12 '14 at 22:50

3 Answers3

4

The rules of the language requires

Point p2 = Point();

to value-initialize p2. Since Point doesn't have a user-defined constructor, value-initialization includes zero-initialization and both p2.X and p2.Y should be zero.

You are seeing a Visual C++ bug (-858993460 is 0xCCCCCCCC, which VC++ fills uninitialized variables with in debug mode). The workaround is to provide a default constructor to Point that explicitly initializes both member variables to zero.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • I agree, can be a visualc++ bug. – rahul Nov 12 '14 at 21:39
  • Just curious: Does `Point p2 = Point()` mean a default-initialization (`Point()`) which means default-initialization for its non-static data members which for integers is value-initialization, followed by copy-initialization for `p2`? – David G Nov 12 '14 at 21:45
  • 1
    @0x499602D2 `Point()` is value-initialization, not default-initialization. Pre-C++11 this means value-initializing the data members, which for `int` means zero-initialization; post-C++11 this zero-initializes the `Point` itself. The whole thing constructs a value-initialized temporary and then copy-initializes `p2` from that, but the temporary is elided in any decent compiler. – T.C. Nov 12 '14 at 21:51
  • What does it mean to zero-initialize the `Point` itself? You mean fill its bits with zero? Also, where does default-initialization come into this? – David G Nov 12 '14 at 21:55
  • @0x499602D2 Yes, all the bits, including padding. If `Point`'s default constructor were nontrivial, then it would be called after the zero-initialization, but otherwise default-initialization doesn't really come into play. – T.C. Nov 12 '14 at 22:01
  • *The rules of the language since 2003 – M.M Nov 12 '14 at 22:56
2

You just need constructor with default values for both fields:

Point() : X(), Y()
{
}
k06a
  • 17,755
  • 10
  • 70
  • 110
0

In C++98 this code leaves p2.X and p2.Y uninitialized.

This is because Point has a user-declared copy-assignment operator, therefore Point is what's known as a non-POD class.

In C++98, Point() for a non-POD class always calls the default constructor (even if implicitly declared); and the implicitly-declared default constructor does not initialize any class members.

In C++03 initialization got a major rework and value initialization was introduced. Point() was now value initialization, which means that the default constructor is called only if it was user-declared.

If you didn't declare a default constructor then the class members are value-initialized even if the class is non-POD. So p2.X and p2.Y must be initialized to 0 in C++03 (and later).


Nowdays we like to pretend C++98 never existed, but apparently MSVC++ still follows it in some initialization cases. (Latest versions of C++Builder 32-bit also use C++98-style initialization in this case too).

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Would be interesting to see if MSVC++ does zero-initialize them if you remove your copy-assignment operator (which is what C++98 specifies - PODs have members zero-intiialized). – M.M Nov 12 '14 at 23:02