0

My following class has undefined behaviour? I think its well defined becouse I m passing constructor arguments by reference. am I right?

class C
{
  int* elem;
  public:
    C(int s[]) :elem(s){}; // Array arguments passed by reference, so its well defined?
    void Print()
    {
      cout << elem[1] << endl;
    }
    ~C()
    {
       delete[] elem; 
    }
};
int main()
{
    C x(new int[2]{1,3});
    return 0;
}
Vito Carleone
  • 157
  • 3
  • 8

2 Answers2

5

There's no undefined behavior in your code. Also, you're not passing by reference, you're passing pointers by value.

Nikos C.
  • 50,738
  • 9
  • 71
  • 96
  • realy? i was thinking In c++ arrays hidden passed by reference. – Vito Carleone Nov 07 '13 at 11:24
  • References and pointers are different things. And arrays are passed by values; the type is then a pointer type. – leemes Nov 07 '13 at 11:25
  • 1
    @VitoCarleone Passing an array by means of simply using its name, passes a pointer to its first element. This is often described as "arrays decay to pointers." But in your case, this isn't what happens anyway. You are passing a pointer to begin with (the `new` operator returns a pointer.) Also, the argument of your constructor, `int s[]`, is just syntactic sugar for `int* s`. The compiler sees it as a declaration of a pointer, not of an array. – Nikos C. Nov 07 '13 at 11:26
4

It's well-defined; you're creating an array, passing a valid pointer to the constructor (which takes a pointer, despite looking as though it takes an array), storing that pointer, and then accessing a valid array element through it.

The only problem is the memory leak - you never delete the array.

UPDATE Now you've added a destructor to delete the array, the class is very dangerous - if you copy it, then both copies will try to delete the same array. That will cause undefined behaviour. You need to either prevent copying, or implement it correctly, per the Rule of Three. You'll also get undefined behaviour if the pointer isn't to an array created with new[].

Once you've learnt how to manage resources by hand, and how difficult it is to get all the details right, you would usually use a library class to do it for you. In this case, std::vector<int> would be ideal. Doing this is sometimes called the "Rule of Zero" (as mentioned in the comments), as it removes the need to write your own destructor or copy/move semantics at all - they all come from the class(es) you're using, which someone has already implemented correctly.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • 1
    ...or rather Rule of Five, or rather Rule of Zero. – Griwes Nov 07 '13 at 11:21
  • Or if you pass it a pointer to anything that is not a dynamically allocated array. – juanchopanza Nov 07 '13 at 11:22
  • @Griwes: Indeed, the Rule of Zero (use classes that already have correct semantics rather than implementing them yourself) is better. There isn't really a Rule of Five, at least as far as correctness is concerned; move semantics are something to think about for efficiency, not necessary for correctness. – Mike Seymour Nov 07 '13 at 11:24
  • sir it is passed by reference? becouse i think i read it long time ago from the book deitel's http://stackoverflow.com/questions/14312970/arrays-passed-by-reference-by-default – Vito Carleone Nov 07 '13 at 11:26
  • Read the first answer of the question you linked. – leemes Nov 07 '13 at 11:27
  • @VitoCarleone: The array is converted to a pointer, which gives a similar effect to passing by reference but without actually using references. – Mike Seymour Nov 07 '13 at 11:27
  • @MikeSeymour, you still need to define a move ctor and assignment operator if you have a raw resource in your class, since default moving will *copy* the resource handle and lead to freeing it twice. So yes, there really is a Rule of Five. – Griwes Nov 07 '13 at 18:26
  • @Griwes: Once you've given the class safe copy semantics, it automatically has safe move semantics. Whether to give it different move semantics is a separate concern; so there's only a Rule of Five if you complicate matters by bundling both concerns together. But I suppose some people like to leap straight to a solution without breaking the problem down, so my opinion is only my opinion. – Mike Seymour Nov 07 '13 at 19:07