Mathematica Assignment Operator C++

Design

Looks OK. Though if you look at some more advanced versions of Matrix classes they have developed some good optimizations. Like multiplications (and other operations) are actually postponed until the resulting cells are actually required. This allows for optimizations where you can see that the result will be a specific value and you don't need to compute all the results for the final matrix).

C++ standard behaviors.

When you define you usually also define . This allows for some good optimizations.

Example:

The normal operation can then be easily defined in terms of this operator:

Now admittedly I have not thought this through completely for matrices (but this would be a normal pattern to follow).

Separation of Concerns

When you design classes you should try and separate resource management from business logic. Your code contains both (resource management is memory management and your business logic is all the matrix code).

Normally you should separate these out into two classes. Luckily you can do this automatically (because the resource management has already been done by ).

I would redefine the class to use to control the memory management part and thus just concentrate on the matrix operations in this class.

Code Review

Const Methods

Methods that do not change the state of the object should be marked const.

These only return a value. So they should be marked const so they can be used in a const context.

Bug

This looks like a recursive call that never returns.

Did you write unit tests?

Initializing dynamic memory.

You don't need to manually reset all memory to zero:

This can be done automatically during allocation by forcing zero construction of each integer vaule.

Assert and exception.

Your assert will never fire:

The call to will never return , so the assert will never fire. If fails, it will throw an exception.

One memory block rather than array of arrays.

You allocate an array of arrays. This means accessing an element becomes two memory accesses.

If you allocate a single block of memory then you only have a single memory access. This does involve you calculating the location of the element:

A technique for overloading to do this can be found here How to overload array index operator for wrapper class of 2D array?.

Assignment Fail

Your assignment operator is broken.

You assume the destination array has enough space to be copied over. This is not generally the case. You will need to check.

The easiest method of implementing the assignment operator is called the Copy and Swap Idiom; you should look it up.

It means the assignment operator is implemented in terms of the copy constructor:

Other quick notes

  • Throw an exception:
  • Virtual Destructor:
  • Prefer Single allocation. You are allocating an array of pointers. Then for each pointer allocating an array of . Rather than do this. Calculate the total area of the matrix just do one allocation for all the elements. When somebody accesses , ou need to multiply by the size of the row then add to get the correct location of the element.
  • If you try and multiply matrices of incompatible sizes, preferably this should be a compile time error (so that you can fix the code before it runs). If you don't know the size of your array until runtime then you should throw an exception to indicate that this is not allowed. Any errors should cause the code to stop working (so that you have to fix the error or explicitly do some coding to tell the user that something went wrong).

In the C++programming language, the assignment operator, , is the operator used for assignment. Like most other operators in C++, it can be overloaded.

The copy assignment operator, often just called the "assignment operator", is a special case of assignment operator where the source (right-hand side) and destination (left-hand side) are of the same class type. It is one of the special member functions, which means that a default version of it is generated automatically by the compiler if the programmer does not declare one. The default version performs a memberwise copy, where each member is copied by its own copy assignment operator (which may also be programmer-declared or compiler-generated).

The copy assignment operator differs from the copy constructor in that it must clean up the data members of the assignment's target (and correctly handle self-assignment) whereas the copy constructor assigns values to uninitialized data members.[1] For example:

My_Arrayfirst;// initialization by default constructorMy_Arraysecond(first);// initialization by copy constructorMy_Arraythird=first;// Also initialization by copy constructorsecond=third;// assignment by copy assignment operator

Return value of overloaded assignment operator[edit]

The language permits an overloaded assignment operator to have an arbitrary return type (including ). However, the operator is usually defined to return a reference to the assignee. This is consistent with the behavior of assignment operator for built-in types (returning the assigned value) and allows for using the operator invocation as an expression, for instance in control statements or in chained assignment. Also, the C++ Standard Library requires this behavior for some user-supplied types.[2]

Overloading copy assignment operator[edit]

When deep copies of objects have to be made, exception safety should be taken into consideration. One way to achieve this when resource deallocation never fails is:

  1. Acquire new resources
  2. Release old resources
  3. Assign the new resources' handles to the object
classMy_Array{int*array;intcount;public:My_Array&operator=(constMy_Array&other){if(this!=&other)// protect against invalid self-assignment{// 1: allocate new memory and copy the elementsint*new_array=newint[other.count];std::copy(other.array,other.array+other.count,new_array);// 2: deallocate old memorydelete[]array;// 3: assign the new memory to the objectarray=new_array;count=other.count;}// by convention, always return *thisreturn*this;}// ...};

However, if a no-fail (no-throw) swap function is available for all the member subobjects and the class provides a copy constructor and destructor (which it should do according to the rule of three), the most straightforward way to implement copy assignment is as follows:[3]

public:voidswap(My_Array&other)// the swap member function (should never fail!){// swap all the members (and base subobject, if applicable) with otherusingstd::swap;// because of ADL the compiler will use // custom swap for members if it exists// falling back to std::swapswap(array,other.array);swap(count,other.count);}My_Array&operator=(My_Arrayother)// note: argument passed by value!{// swap this with otherswap(other);// by convention, always return *thisreturn*this;// other is destroyed, releasing the memory}

Assignment between different classes[edit]

C++ supports assignment between different classes, both via implicit copy constructor and assignment operator, if the destination instance class is the ancestor of the source instance class:

classAncestor{public:inta;};classDescendant:publicAncestor{public:intb;};intmain(){Descendantd;Ancestora(d);Ancestorb(d);a=d;return0;}

Copying from ancestor to descendant objects, which could leave descendant's fields uninitialized, is not permitted.

See also[edit]

References[edit]

External links[edit]

  1. ^Stroustrup, Bjarne (2000). The C++ Programming Language (3 ed.). Addison-Wesley. p. 244. ISBN 978-0-201-70073-2. 
  2. ^Working Draft, Standard for Programming Language C++, Section 17.6.3.1, Table 23; http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
  3. ^Sutter, H.; Alexandrescu, A. (October 2004), C++ Coding Standards, Addison-Wesley, ISBN 0-321-11358-6 

0 Replies to “Mathematica Assignment Operator C++”

Lascia un Commento

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati *