0

Most people will probably recommend that I use a std::vector or even a std::array but the custom array class below uses a C array and it works, I just need some explanation as to why it works.

For reference, here is a common way to initialize a dynamic C style array:

int* elements = new int[size];

Now below, we have our own custom array class that initializes a dynamic C style array within the initializer list. The problem is that I don't understand how the C array is being initialized within the initializer list.

class myArray 
{
public:

    myArray(int size) : size(size), elements(new int[size])
    {
        std::cout << "Constructed array of size " << size << std::endl;
    }

    ~myArray()
    {
        delete[] elements;
        std::cout << "Deleted elements" << std::endl;
    }

    int getSize() const { return size; }

private:
    int size;
    int* elements;  // our C style array
};

Thank you

UPDATE

I would like to clarify my question a little more. Below is the old fashioned "assignment" way that I would normally initialize the dynamic C array:

myArray(int size)
{
    elements = new int[size];
    // elements(new int[size]); // why will line only work in initializer list?
    std::cout << "Constructed array of size " << size << std::endl;
}

But please see the commented line. Why does that not work but it does work within the initializer list?

Caroline Beltran
  • 888
  • 2
  • 9
  • 22
  • *the custom array class below uses a C array and it works* ... no, it doesn't really work. Try making a copy of a `myArray` instance. See [rule of three](https://stackoverflow.com/q/4172722/241631). – Praetorian Jan 04 '17 at 19:00
  • @Praetorian, I wanted to keep the class as concise as possible. I am not interested in any other constructors in this example. Please see the UPDATE, I added a little more information to my question. See the line that is commented out. I want to know why the commented line will work only in the initializer list. – Caroline Beltran Jan 04 '17 at 19:07
  • 1
    That's how C++ constructor initializers work. It's similar to an argument to a constructor. Have you read [a good C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list?lq=1)? I highly recommend The C++ Programming Language. It's an investment that will pay off well. – Rob K Jan 04 '17 at 19:15
  • 1
    The commented line won't compile because there's a difference between initialization and assignment. [This answer](https://stackoverflow.com/a/8523361/241631) explains things pretty well. And you really should be learning C++ from a book instead of random code samples. – Praetorian Jan 04 '17 at 19:16
  • @RobK, If you notice on the UPDATE part, I would expect that the commented line would compile but it does not. Yet it works in the initializer list--confusing :( – Caroline Beltran Jan 04 '17 at 19:17
  • 1
    It's the difference between assignment and construction. You can only use that function-style syntax to assign a value as part of construction. In the initializer list, it's actually constructing `elements` as part of constructing the `myArray` instance. As part of a statement in the body of a function though, the compiler sees it as an attempt to call a function. – Rob K Jan 04 '17 at 19:28

2 Answers2

3

I don't understand how the C array is being initialized within the initializer list.

here:

myArray(int size) : size(size), elements(new int[size])

elements are basicly assigned value returned by new int[size]

You could rewrite it as :

myArray(int size)
{
    this->size = size;
    elements = new int[size];
    std::cout << "Constructed array of size " << size << std::endl;
}

[edit]

This:

// elements(new int[size]); // why will line only work in initializer list?

will not work in the function body, because in this place compiler thinks that you want to call a function named elements, but there is no such function.

The fact that it works in the initializer list is because that is how the language syntax was made.

marcinj
  • 48,511
  • 9
  • 79
  • 100
  • I am familiar with initializing the array exactly like in your code example. Please see the UPDATE post for more details to my question. – Caroline Beltran Jan 04 '17 at 19:12
  • 1
    @CarolineBeltran when compiler see `elements(new int[size]);` in the function body it thinks `elements` is a function. That is why this construct is not allowed in the function body. – marcinj Jan 04 '17 at 19:22
  • 1
    btw. you may also find intializer list with braced initializations, like: `size{size}`, the difference from `size(size)` is that the former prohibits narrowing conversions. – marcinj Jan 04 '17 at 19:30
  • The function style syntax that only works in the initializer list is so strange to me. I have not learned about braced initializations next. But I do have one last question. Why can't it be initialized as follows: myArray(int size) : size(size), (elements = new int[size]) – Caroline Beltran Jan 04 '17 at 19:40
  • 1
    Thats is how c++ language syntax was made, each language has its own grammar, whether its english or C++ there is no difference, for C++ you can see here http://eel.is/c++draft/gram.special its mem-initializer-list. `(elements = new int[size])` is not valid because compiler expects class member or base class name before `(`. – marcinj Jan 04 '17 at 19:53
  • 1
    C++ syntax is quite complicated, from this link you may find that expression-list allows to use quite complicated logic in initializer lists, example is `myArray(int size) : size(size), elements(this->elements = new int[size])` - not that I encourage it as it makes no sense. This would make more sense: `myArray(int size) : size(size), elements(size==0?nullptr:new int[size])` – marcinj Jan 04 '17 at 19:53
1

There are two initialization way. First way is trivial (literal) types initialization. Second way is the non-trivial type init.

For difference between this types see What is a non-trivial constructor in C++?

Also you can see, that trivial behavior may be different if you call default constructor manually or if it can be called implicitly. This will determine whether the memory is initialized (zerofill) with the allocation.

Some usefull information about hidden initialization you can find in book Anthony Williams "C++ Concurrency in Action: Practical Multithreading"

Community
  • 1
  • 1
Titch
  • 153
  • 1
  • 1
  • 10
  • I am going to read the information you directed me to, but if possible, please see the UPDATE of my original post with more details of what I don't understand. – Caroline Beltran Jan 04 '17 at 19:15