1

In my understanding, under usual conditions, array is being allocated memory at compile time, but what happens when array is a member variable, and there is pretty much nothing to allocate memory to during compilation. Does it get implicitly dynamically-allocated, when instance of that class is created?

class Arr{
   public:
   int arr[10];
};

Arr doSomething(Arr &arg){
   return arg; //copy of arg created; 'copy=new int[10]' at this point?
}

int main(){
   Arr temp; 
   doSomething(temp);

   //if returned object's array was dynamically initialized
   //will it result the array in temp being released twice?
}

UPD. In my case, situation rises when I try to subract A-B where B>A. In these cases I can access array to read from it, but modifying its values leads to garbage. Moreover, final output in main is fine. Here's full code:

#include <iostream>

using namespace std;

const int MAX_ARRAY_SIZE=256;

char* getOperatorIndex(char* equationString);
bool isOperator(char characterDec);
int* toIntArray(char* firstInA, char* lastInA, int* firstInB);

class Number{
    int* firstInNumber;
    int* lastInNumber;
    int number[MAX_ARRAY_SIZE];

    public:
    Number();
    ~Number();
    bool operator<(Number& b);
    int& operator[](int index);
    Number operator-(Number& b);
    void print();
    int length(){return lastInNumber-firstInNumber;}
    int*& lastPtr(){return lastInNumber;}
    int*& firstPtr(){return firstInNumber;}
};

Number::Number(){
    firstInNumber=number;
    lastInNumber=number;
}

Number::~Number(){
    cout<<"number destroyed"<<endl;
}

int& Number::operator[](int index){
    return number[index];
}

bool Number::operator<(Number& b){
    if(length()>b.length())return false;
    if(length()<b.length())return true;

    for(int a=0;a<length();++a){
        if(number[a]>b[a])return false;
        if(number[a]<b[a])return true;
    }
    return false;

}

void Number::print(){
    for(int a=0; a<=length(); ++a){
        cout<<number[a];
    }
    cout<<endl;
}

Number Number::operator-(Number& b){

    Number result;

    if(*this < b)
    {
        result=b-*this;
        cout<<*result.lastPtr()<<endl;
        result.print();
        *result.lastPtr()*=-1; // GARBAGE HERE
        cout<<*result.lastPtr()<<endl;
        return result;
    } 

    result[0]=0;

    for(int q=0; q<=length(); ++q)
    {

        if(b.length()-q >= 0)
        {
            result[q]+=(*this)[length()-q]-b[b.length()-q];

            if(result[q] < 0)
            {
                result[q]+=10;
                result[q+1]=-1;

            } 
            else
            {
                result[q+1]=0;
            }

        }
        else
        {
            result[q]+=(*this)[length()-q];

        }

    ++result.lastPtr(); 
    }

    do{
        --result.lastPtr();
    }while(!*result.lastPtr());

    return result;
}

int main(){
    char equationArray[MAX_ARRAY_SIZE*2+1];  // operandA(<=256) operator(1) operandB(<=256)
    Number a,b;

    cin>>equationArray;
    char* operatorPtr=getOperatorIndex(equationArray);

    a.lastPtr()=toIntArray(equationArray, operatorPtr, a.firstPtr());
    b.lastPtr()=toIntArray(operatorPtr+1, operatorPtr+strlen(operatorPtr), b.firstPtr());

    a.print();
    b.print();

    Number c;
    switch(*operatorPtr){
        case '-':
            c=a-b; 
            break;
    }
    c.print();

}


char* getOperatorIndex(char* equationString){
    while(!isOperator(*++equationString));   
    return equationString;
}

bool isOperator(char characterDec){
    if(characterDec>='*' & characterDec<='/')return true;
    return false;
}


int* toIntArray(char* firstInA, char* lastInA, int* firstInB){
    while(lastInA-firstInA>0){
        *firstInB=*firstInA-'0';
        ++firstInB;
        ++firstInA;
    }
    return --firstInB;  
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Misha.P
  • 300
  • 1
  • 2
  • 9
  • Did you try running this program? To be honest, I'm also not sure about what will happen if you copy-construct something that has a dynamically allocated array. – Giora Guttsait Apr 13 '17 at 10:56
  • Could you clarify what you're asking - why do you imagine that an array member variable would be different to a non-array member variable? – Oliver Charlesworth Apr 13 '17 at 10:57
  • we can see your class definition as a typedef (if it doesn't have static member variables) and as type it doesn't allocate memory. – olivecoder Apr 13 '17 at 10:59
  • @OliverCharlesworth, because I have a bigger program which deals with this situation exactly: At some point the returned array, behaves as expected for read, but when I try to write something it gives garbage values. – Misha.P Apr 13 '17 at 11:00
  • 1
    @MikeMike, can you provide the code that reproduces such behavior? – WhiZTiM Apr 13 '17 at 11:04

1 Answers1

3

All data members of a class have the same storage-duration as the class' object created. Hence in:

int main(){
   Arr temp; 
   doSomething(temp);
}

The data member temp.arr which is of type int[10]; also has automatic storage-duration.. (or what is inappropriately known as "stack object")


Arr doSomething(Arr &arg){
   return arg; //copy of arg created; 'copy=new int[10]' at this point?
}

No, there is no heap allocation here. rather a member-wise copy by the implicit copy constructor. See How are C++ array members handled in copy control functions?

Community
  • 1
  • 1
WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • What if there was a pointer as a member variable, that would point to the last element in array? Would it cause, when temporary object is released, the pointee variable in array to be released as well? – Misha.P Apr 13 '17 at 11:06
  • @MikeMike, if there was a pointer, then we can assume your objects of that class manages a resource. In that case, you **should** definitely define and implement your special member functions. This is because, the implicit copy constructor will only copy the value of the pointer, the pointer will still point to the last element of the array of the **old** object. The problem is now the newly copied pointer data member is not pointing to the end of an array of its own object, rather, another object. – WhiZTiM Apr 13 '17 at 11:12
  • @Mike Mike - No. When a temporary object containing a pointer is released or otherwise destroyed, the pointer is unaffected by default. It is possible to write a destructor for the object's class that explicitly does something with the pointer, but that requires deliberate action by the programmer. C++ is not garbage collected. – Peter Apr 13 '17 at 11:13