-2

I try to make an array and take input and then simply showing the output on the screen but uses classes and objects, Here is my code:

#include<iostream>
using namespace std;
class array{
    int ar[], n;
    public:
        void input();
        int display();
}obj;
void array::input(){
    cout<<"Enter item size: ";
    cin>>n;
    int ar[n]={};
    for(int i=0; i<n; i++){
        cout<<"Enter value at index "<<i<<" : ";
        cin>>ar[i];
    }

}
int array::display(){
    cout<<"You Entered: ";

    for(int i=0 ; i<n; i++){
        cout<<ar[i];
    }
}
int main(){

    obj.input();
    obj.display();

}

In the sample run, I entered 1 and 2 and I am expected to get 1 and 2.

Tahir Musharraf
  • 97
  • 3
  • 11

2 Answers2

3

Two problems in your code.

First int ar[] should not compile. I get the following error:

prog.cc:4:12: error: ISO C++ forbids flexible array member 'ar' [-Wpedantic]
     int ar[], n;
            ^

Next, in array::input() you create a completely new array int ar[n]={}; which is also not valid c++. Array sizes must be compiletime constants. Moreover, this array shadows the member and is unrelated to it (apart from having the same name). So this ar is gone once you return from the method. You never write anything into the member ar.

If you dont know the size in advance you should use a std::vector:

#include <iostream>
#include <vector>

class array{
    std::vector<int> ar;
    public:
        void input();
        int display();
};
void array::input(){
    std::cout << "Enter item size: ";
    int n;
    std::cin >> n;
    ar.resize(n);
    for(int i=0; i<n; ++i){
        std::cout << "Enter value at index " << i << " : ";
        std::cin >> ar[i];
    }

}
int array::display(){
    std::cout<<"You Entered: ";

    for(int i=0 ; i<n; ++i){
        std::cout << ar[i];
    }
}
int main() {
    array obj;    
    obj.input();
    obj.display();    
}

PS: read here why using namespace std; is bad practice: Why is "using namespace std" considered bad practice?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

IMHO user463035818s answer is sufficient, but for all that OP asked me

how to fix this compiler issue.

The recommended fix would be by design i.e. like shown in user463035818s answer.

So, I want to elaborate how to fix the sample code of OP (with "minimal" changes). That might make obvious why user463035818s answer is the better one. (I repeated the link three times – it should be clear to everybody that I consider this as the better solution.)

The actual compiler error (or warning or feature accepted by compiler extension): OP used int ar[] a C array as class member without denoting the size.

This is called Flexible array member but it is a C99 feature (not supported by the C++ standard).

The linked Wikipedia article provides a nice example:

struct vectord {
    size_t len;
    double arr[]; // the flexible array member must be last
};

To be clear, flexible array members don't provide automatic allocation. They just represent an array of arbitrary length. The programmer is responsible to grant sufficient storage for that array. Hence even in C, and with the resp. syntax adjustments, this code would have been broken.

Some C++ compilers adopt features from C as (proprietary) extension. That's the reason that OP got responses ranging from "On my side, it works."1 to "This is a compiler error." However, I would consider usage of such extensions as bad style in general. With different compiler settings or a different compiler, this might not work anymore.

1 This is not the only issue of OPs code. "It works" might be merely bad luck. OPs code has Undefined Behavior. One kind of Undefined Behavior is "It works" which is not the best one because programmer might believe that the code is fine.


A lot of higher level languages (Java, C#, Python) tries to cover memory allocation and storage management "under the hood" completely because it's not quite easy to make this always correct and consider every edge case sufficiently. This might cause an additional performance impact for the administration of memory. In C and C++, the programmer has ful control over memory allocation. It's both a blessing and a curse. The standard library of C++ provides a variety of tools to make programmers allocation life easier.

For dynamic arrays, the tool of choice is the template class std::vector. It provides an overloaded operator[] which allows that it can be accessed just like an array. It provides methods like reserve() and resize(). The storage is internally managed.

I would strongly recommend to use std::vector but there is also the possibility to do it using new[] and delete[].


For this, the class array might look as follows:

class array {
    int *ar; // a raw pointer for storage
    int n; // the current size of array
  public:
    int display();

int* and int are plain old data types → implicit construction leaving them uninitialized. So, there really should be defined at least a default constructor.

    array(): ar(nullptr), n(0) { }

The input() method has to ensure proper storage.

    void input()
    {
      // release old memory (if there is one)
      delete[] ar; ar = nullptr; n = 0;
      // input
      std::cout << "Enter item size: ";
      std::cin >> n;
      if (n <= 0) return;
      ar = new int[n];
      for (int i = 0; i < n; ++i) {
        std::cout << "Enter value at index " << i << ": ";
        std::cin >> ar[i];
      }
    }

When an instance of class array is deleted it should release the internal storage. Otherwise, the allocated memory pointed by ar will be orphaned and lost until process is terminated by OS. Such lost memory is called memory leak.

    ~array() { delete[] ar; }

Please, note that calling delete[] (or delete) with a nullptr is valid. Hence, no extra if (ar) is needed.

Finally, we have to obey the Rule of three. The compiler generates implicitly copy constructor and copy assignment operator which will copy the class array members by value. Copying a pointer by value does not mean that the contents (it points to) is copied. It just means copy the pointer (address value). Hence, an (accidental, unintended) copy of class array could result in two instances of class array which members ar point to the same memory. Once, one of them deletes that memory, the ar of the other becomes dangling i.e. points to released memory. (Bad!) If the other instance is destroyed also it will delete[] ar again. This is double deleting which is prohibited. (Bad again!)

One option could be to define copy constructor and copy assignment to handle this appropriately by making a deep copy of ar contents (with another new[]). However, if copy is not intended, an alternative is to just explixitly prohibit copy for class array:

    array(const array&) = delete;
    array& operator=(const array&) = delete;
};

Putting this althogether in array.cc:

#include <iostream>

class array {
    int *ar; // a raw pointer for storage
    int n; // the current size of array
  public:
    array(): ar(nullptr), n(0) { }
    ~array() { delete[] ar; }
    array(const array&) = delete;
    array& operator=(const array&) = delete;

    void input();
    void display();
};

void array::input()
{
  // release old memory (if there is one)
  delete[] ar; ar = nullptr; n = 0;
  // input
  std::cout << "Enter item size: ";
  std::cin >> n;
  if (n <= 0) return;
  ar = new int[n];
  for (int i = 0; i < n; ++i) {
    std::cout << "Enter value at index " << i << ": ";
    std::cin >> ar[i];
  }
}

void array::display()
{
  std::cout << "You Entered: ";
  for (int i = 0; i < n; ++i) {
    std::cout << ar[i];
  }
  std::cout << '\n';
}

int main()
{
  array obj;
  obj.input();
  obj.display();
  return 0;
}

Compiled and tested:

$ g++ -std=c++11 -Wall -pedantic array.cc && ./a.out
Enter item size: 1
Enter value at index 0: 2
You Entered: 2

$

Live Demo on coliru


The last sentence in OPs question is a bit unclear for me (although I assume it's just bad worded):

In the sample run, I entered 1 and 2 and I am expected to get 1 and 2.

Either input is 2 1 2 then output is 1 2.
Or input is 1 2 then output is 2.

Please note that array::input() expects first input of array::n but array::display() doesn't output array::n.

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56