I'm simply adding two numeric arrays of size 3 and printing the result. So, if:
A = 4,6,1
B = 8,5,6
Then the result is 12,11,7. The problem for me is I am printing exponential numbers i.e. -1.28823e-231. Can anyone tell me why? I have tried to keep as little code in here as possible. First it's main() then the header then the source material. Many thanks.
NumericArray<double> doubArray5; //test + operator
cout << "doubArray5" << endl;
doubArray5 = doubArray2 + doubArray3;
for (int i = 0; i < doubArray5.Size(); i++)
cout << doubArray5[i] << endl;
cout << endl;
#ifndef NUMERICARRAY_H
#define NUMERICARRAY_H
#include "array.h"
#include <iostream>
namespace Cary
{
namespace Containers
{
template<typename T>
class NumericArray: public Array<T>
{
public:
NumericArray<T>(); //default constructor
NumericArray<T>(int i); //constructor with one argument
~NumericArray<T>(); //destructor
NumericArray<T>(const NumericArray<T>& source); //copy constructor
NumericArray<T>& operator = (const NumericArray<T>& arr1); //assignment operator
NumericArray<T> operator * (double factor) const; //scale
NumericArray<T>& operator + (const NumericArray<T>& arr2) const; //add
T dotProduct(const NumericArray<T>& na) const; //dot product
};
}
}
#ifndef NUMERICARRAY_CPP
#include "NumericArray.cpp"
#endif
#endif
template<typename T>
NumericArray<T>& NumericArray<T>::operator + (const NumericArray<T>& arr) const //add
{
if (Array<T>::Size() != arr.Size()) throw OutOfBoundsException();
NumericArray<T> tempArray = NumericArray(Array<T>::Size());
for (int i = 0; i < Array<T>::Size(); i++)
tempArray[i] = Array<T>::GetElement(i) + arr.GetElement(i);
return tempArray;
}
Idiomatically (i.e. based on the "behaves like int" guideline when overloading numeric operators), operator+() usually returns by value, not by reference, since the result of addition is a distinct value (or object) from either of those being added.
Specifically, as Mike Seymour also mentioned in comments, your operator+() is returning a reference to a local variable that ceases to exist when operator+() returns. That causes the caller to exhibit undefined behaviour if it subsequently attempts to use the returned reference.
You are returning a reference to a local variable (tempArray in operator +).
When the function returns, tempArray is destroyed. The caller then tries to use the reference to a now-destroyed object, and reads garbage.
Related
I want to know the internals of the move function in C++.
For that, I aim to make my own implementation of the move function called move2.
Here is my implementation with prints to track memory allocation.
#include <iostream>
#include <vector>
using namespace std;
void * operator new(size_t size) {
cout << "New operator overloading " << endl;
void * p = malloc(size);
return p;
}
void operator delete(void * p) {
cout << "Delete operator overloading " << endl;
free(p);
}
template<typename T>
T move2(T& input) {
cout << "Running move2 " << endl;
return (T&&)input;
}
int main()
{
{
cout<<"Test#1"<<endl;
vector<int> temp1(10,4);
vector<int> temp2 = temp1;
}
{
cout<<"Test#2"<<endl;
vector<int> temp3(10,4);
vector<int> temp4 = (vector<int>&&)(temp3);
}
{
cout<<"Test#3"<<endl;
vector<int> temp5(10,4);
vector<int> temp6 = move(temp5);
}
{
cout<<"Test#4"<<endl;
vector<int> temp7(10,4);
vector<int> temp8 = move2(temp7);
}
return 0;
}
Here is the output
Test#1
New operator overloading
New operator overloading
Delete operator overloading
Delete operator overloading
Test#2
New operator overloading
Delete operator overloading
Test#3
New operator overloading
Delete operator overloading
Test#4
New operator overloading
Running move2
Delete operator overloading
I want to know if my implementation of move2 is correct and can I use it in production?
Update:
I found the GCC implementation of move
/**
* #brief Convert a value to an rvalue.
* #param __t A thing of arbitrary type.
* #return The parameter cast to an rvalue-reference to allow moving it.
*/
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
std::move() takes in a forwarding reference, and returns a T&& rvalue reference. Your move2() does neither. It takes in an lvalue reference, and returns a T by value.
Your code "works" due to copy elision avoiding a temporary object being created when your function returns a new object by value, thus allowing temp8 to be constructed directly with your type-casted reference to input, thus transferring ownership of its data. That is not because of a proper move2() implementation, though.
Try this instead:
template<typename T>
std::remove_reference_t<T>&& move2(T&& input) {
...
return static_cast<std::remove_reference_t<T>&&>(input);
}
class Array
{
private:
int *ptr;
int size;
public:
Array& operator = (const Array& rhs);
};
Array& Array::operator = (const Array& rhs)
{
ptr = new int [rhs.size];
size = rhs.size;
for( int i = 0; i < size; i++ )
ptr[i] = rhs.ptr[i];
return *this;
}
int main()
{
Array a;
Array b;
a = b;
}
What are problems with this code?
First thing I can observe is that size's value have not been defined. So there will be an error.
size is private so I can't assign it a value from main, yet that is a parameter of assignment operator. Where do I assign the value?
I tried to assign the value of rhs.size inside the definition of the = operator but then it threw segmentation fault. Why?
I don't understand what are they intending to do with this for loop:
for( int i = 0; i < size; i++ )
ptr[i] = rhs.ptr[i];
I want to understand what is happening with this code.
Before we can talk about the operator=, we need to realise that the class is fundamentally broken: it has no working constructor, and it is violating the rule of three, and is therefore not managing its resources properly.
After these two points have been fixed, (but really only after that!), we can turn to the implementation of operator=. Let’s first address your three points:
First thing I can observe is that size's value have not been defined. So there will be an error.
Once the class has a working constructor, size will have a defined value.
size is private so I can't assign it a value from main, yet that is a parameter of assignment operator. Where do I assign the value?
In the constructor.
I tried to assign the value of rhs.size inside the definition of the = operator but then it threw segmentation fault. Why?
How did you assign it? What value did you try to give it? Since rhs is const& (as it should be!), you can’t assign to its members — this will result in a compile-time error, not in a segmentation fault. In fact, the size of rhs is part of the precondition of the function. It must not be modified (hence the use of const&).
Here are some more things that are wrong with the function:
It does not guard against self-assignment (what if this == &rhs?).
It does not deallocate previously-allocated memory in ptr.
With no constructor there's no way to allocate memory in the first place to copy, no way to assign size, and so on. You need to add that capability to test your copy feature.
I've sketched in some more code here to get this more operational, though there's obviously still a lot of work to do:
#include <iostream>
class Array
{
private:
int *ptr;
int size;
public:
// Simple default constructor
Array(int size = 0) : ptr(new int[size]), size(size) {
}
int getSize() const { return size; };
Array& operator=(const Array& rhs);
};
Array& Array::operator=(const Array& rhs)
{
// Delete any previous allocation
delete[] ptr;
ptr = new int[rhs.size];
size = rhs.size;
for( int i = 0; i < size; i++ )
ptr[i] = rhs.ptr[i];
return *this;
}
int main()
{
Array a(5);
Array b;
std::cout << "a size=" << a.getSize() << std::endl;
b = a;
std::cout << "b size=" << b.getSize() << std::endl;
}
Keep in mind it's called operator= as one word, not operator = all spaced out. The syntax doesn't care, but programmers do as it parses visually in a whole different way.
Note that this is a long way from idiomatic C++, like using size_t is preferable for "size" type arguments, but there's a long, long list of things you'll need to pick up and learn as you go.
So, I'm fairly new to C++ but I have done lots of C programming. Partly as an exercise, and also partly because I don't have a matrix package that permits the fine-grained control over things that I would like, I have been writing my own matrix class mtMatrix and overloading various operators to let me write equations conveniently. I've overloaded +,-,/, and * to perform element-wise arithmetic operations, after checking that the matrices are of the same size, while full-on matrix multiplication is done by the class method Mult(). I've further overloaded +,-,/, and * to multiply matrices by scalars, so I can have a mtMatrix M and write "mtMatrix T = M * 2.0" to get a new matrix whose entries are twice as large as the old one. However, when I try to write "mtMatrix T = 2.0 * M" I run into problems, and I'm not sure how I would write the overloading for +,-, and * to accomplish this, even though what I would want is precisely the same result as if I were to type "mtMatrix T = M * 2.0." It seems that the contents of the overloading function would be identical in the two cases, but the signature of the function would be different. Can anyone point me in the right direction?
You need to create an operator associated with an lvalue as int. The operator* you have declared in your class has as lvalue 'this' therefore M*2.0 works.
In order to create an operator associated as lvalue for int you need to declare it outside the class, and if the operator has as rvalue an object of your class then you need to declare it as friend so it can access the private values.
Below is an example, where the class in not a matrix but simulates the behavior you want to accomplish.
#include <iostream>
class M
{
int value_;
public:
M(int value):value_(value){}
int& operator()() { return this->value_; }
int operator()() const { return this->value_; }
int operator*(int value) { return this->value_ * value; }
friend int operator*(int, const M&) ; //so it can access the M private objects
};
int operator*(int value, const M& other)
{
return value * other.value_;
}
int main()
{
M m0(10);
M m1(5);
m0() = m0() * 10;
std::cout << m0() << std::endl;
m0() = 10 * m1();
std::cout << m0() << std::endl;
return 0;
}
I'm pretty new to C++ and as an exercise (and perhaps eventually .Net utility) I'm doing a pointer wrapper (actually in C++/CLI, but this applies to C++ as well). This pointer wrapper (called Apont) currently behaves just like a pointer would, as the test below can show, if lines marked 1. and 2. are commented out:
int main(array<System::String ^> ^args)
{
double ia = 10; double ip = 10;
double *p = &ip; // pointer analogy
Apont<double> ^a =
gcnew Apont<double>(ia); // equivalent to what's below, without errors
a = ~ia;/* 1. IntelliSense: expression must have integral or unscoped enum type
error C2440: '=' : cannot convert from 'double' to 'Utilidades::ComNativos::Apont<T> ^'
error C2171: '~' : illegal on operands of type 'double'*/
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
ia = 20; ip = 20;
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
*p = 30; // pointer analogy
a->Valor = 30; // does exacly what's below, without errors
!a = 30;/* 2. IntelliSense: expression must be a modifiable lvalue
error C2106: '=' : left operand must be l-value */
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
//a->Dispose();
Console::ReadKey();
p = nullptr;
return 0;
}
There are two things I don't like here, marked with 1. and 2. in the code comments, before the lines with errors. The operator~ (see 1.) is defined outside Apont, below:
template<typename T> static Apont<T>^% operator ~(T& valor)
{
return gcnew Apont<T>(valor);
}
I think this one has to be defined outside Apont, but I'm not sure. I cannot understand very well the errors it produces (these are, of course, in the use, not in the definition).
To set the value to which the instance of Apont refers I must use a property (the line marked 2. doesn't work, with errors in the setting usage only), Apont::Valor, which is the equivalent to use *p. What I'd like to do is as I use *p to get or set the value it points to, use !a with the same effect on Apont. Here's Apont::operator!()'s current definition:
T operator !()
{
return Valor;
}
As you can see in 2. (comment in the code, before the respective errors), it doesn't work for setting a value. Maybe I should return a reference? Make another operator with the same name, perhaps outside the class? I tried several options, however, I got similar errors, and came out more confused.
The question is: how can I make an operator that behaves like & (in this case, ~) and one that behaves like * (in this case, !, for dereference, but that behaves like Apont::Valor, whose old definition you can see below)?
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado) // means "disposed && ErrorIfDisposed"
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo) // means "ErrorIfNull"
throw gcnew NullReferenceException();
else
return 0;
// don't worry, this is not default behavior, it is returned only if you want to ignore all errors and if the pointer is null
}
void set(T valor)
{
*pointer = valor;
}
}
Let me recap in a new answer for clarity.
Solving the ! operator is easy, as I said in my previous answer, just add a reference.
So for the operator ~, the goal was to have it behave like the & operator and call the constructor of the pointer wrapper class.
I don't think that is possible. It is certainly possible for user defined objects, but I don't think it is possible to overload unary operators for builtin types. So there are three solutions depending on what you prefer:
The first one does exactly what you want, but will break for primitive types:
#include <iostream>
template<typename T>
struct A {
T* payload;
A()
: payload(NULL){}
A(T *ptr)
: payload(ptr) {}
T& operator !(){
return *payload;
}
};
// this will not work for primary types
template<typename T>
A<T> operator ~(T &b){
return A<T>(&b);
}
struct B{
int test;
};
int main(){
B b; b.test = 4;
A<B> a;
a = ~b; // I think this is what you want
std::cerr << (!a).test << std::endl;
// this does not work
//int i = 4;
//A<int> a;
//a = ~i;
}
Second solution: use a compound assignment operator. Pros are the side effects are minimal, cons is this is not very intuitive and might break the nice design you had in mind.
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
};
template<typename T>
A<T>& operator &=(A<T> &a, T& b){ // should be friend of the above
a.payload = &b;
return a;
}
int main(){
int i = 3;
A<int> a;
a &= i;
std::cerr << !a << std::endl;
}
Third solution: overload the basic assignment operator. This is more intuitive to write but has a lot of side effects:
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
A<T>& operator = (T & b) {
payload = &b;
return *this;
}
};
int main(){
int i = 3;
A<int> a;
a = i;
std::cerr << !a << std::endl;
}
Someone might have a solution to hijack the operators for primitive types, but i can't think of any simple solution.
If i understood your code correctly, you want the operator ~ to return a copy of the pointer wrapper and the operator ! to act as dereference?
In this case, you can define the unary operator ~ inside the Apont class which calls a copy constructor. And the operator ! has to return a reference indeed if you want to asign a value.
I think the following c++ code defines what you want to do (I renamed Apont to A):
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr)
:payload(ptr) {}
A(const A&other)
:payload(other.payload) {}
T& operator !(){
return *payload;
}
T* operator ~(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
PRINT(i);
A<int> a(&i);
!a = 1;
PRINT(i);
A<int> b = ~a;
!b = 2;
PRINT(i);
}
The output of the code above is:
i = 0
i = 1
i = 2
According to your comments, you said you wanted the operator ! to behave exactly like the wrapped pointer. You can do so, but then the syntax changes and you need to dereference it to assign a new value (because it is a pointer...). ie something like:
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr): payload(ptr) {}
// this now behaves like accessing the wrapped pointer directly
T*& operator !(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
int j = 999;
PRINT(i);
A<int> a(&i);
*(!a) = 1; // note the change of syntax here
PRINT(*!a); // and here
!a = &j; // but now you can change the wrapped pointer through the operator
PRINT(*!a);
}
I just got a seg fault in overloading the assignment operator for a class FeatureRandomCounts, which has _rects as its pointer member pointing to an array of FeatureCount and size rhs._dim, and whose other date members are non-pointers:
FeatureRandomCounts & FeatureRandomCounts::operator=(const FeatureRandomCounts &rhs)
{
if (_rects) delete [] _rects;
*this = rhs; // segment fault
_rects = new FeatureCount [rhs._dim];
for (int i = 0; i < rhs._dim; i++)
{
_rects[i]=rhs._rects[i];
}
return *this;
}
Does someone have some clue? Thanks and regards!
*this = rhs;
calls operator=(), which is the function you are writing. Cue infinite recursion, stack overflow, crash.
Also, if you used a std::vector rather than a C-style array, you probably would not need to implement operator=() at all.
As mentioned, you have infinite recursion; however, to add to that, here's a foolproof way to implement op=:
struct T {
T(T const& other);
T& operator=(T copy) {
swap(*this, copy);
return *this;
}
friend void swap(T& a, T& b);
};
Write a correct copy ctor and swap, and exception safety and all edge cases are handled for you!
The copy parameter is passed by value and then changed. Any resources which the current instance must destroy are handled when copy is destroyed. This follows current recommendations and handles self-assignment cleanly.
#include <algorithm>
#include <iostream>
struct ConcreteExample {
int* p;
std::string s;
ConcreteExample(int n, char const* s) : p(new int(n)), s(s) {}
ConcreteExample(ConcreteExample const& other)
: p(new int(*other.p)), s(other.s) {}
~ConcreteExample() { delete p; }
ConcreteExample& operator=(ConcreteExample copy) {
swap(*this, copy);
return *this;
}
friend void swap(ConcreteExample& a, ConcreteExample& b) {
using std::swap;
//using boost::swap; // if available
swap(a.p, b.p); // uses ADL (when p has a different type), the whole reason
swap(a.s, b.s); // this 'method' is not really a member (so it can be used
// the same way)
}
};
int main() {
ConcreteExample a (3, "a"), b (5, "b");
std::cout << a.s << *a.p << ' ' << b.s << *b.p << '\n';
a = b;
std::cout << a.s << *a.p << ' ' << b.s << *b.p << '\n';
return 0;
}
Notice it works with either manually managed members (p) or RAII/SBRM-style members (s).
*this = rhs; // segment fault
This is definitively not the way to do it. You call = recursively, not calling the built in assignment operator. Assign variables one by one. Don't be lazy.
The following line:
*this = rhs; // segment fault
will recursively call your operator=() function resulting in a stack overflow.
You should probably replace it with straight-forward assignments of the various member fields.
As Neil said, using something like std::vector<> will remove much of the responsibility away from your code. If for whatever reason you can't or don't want to use std::vector<>, you might also want to consider using the 'swap idiom' for your assignment operator. This will make the function exception safe (if the allocation of the memory for FeatureCount array fails and throws an exception, the original object that's being assigned to will be left unchanged). Something like the following:
void FeatureRandomCounts::swap( FeatureRandomCounts& other)
{
FeatureCount* tmp_rects = other._rects;
int tmp_dim = other._dim; // or whatever type _dim is
// similarly for other members of FeatureRandomCounts...
// now copy the other contents to
this->_rects = other._rects;
this->_dim = other._dim;
// assign other members of rhs to lhs
other._rects = tmp_rects;
other._dim = tmp_dim;
// etc.
return;
}
Now your assignment can look like:
FeatureRandomCounts & FeatureRandomCounts::operator=(const FeatureRandomCounts &rhs)
{
FeatureRandomCounts tmp( rhs); // make a copy
tmp.swap( *this); // swap the contents of the copy and *this
return *this;
// the contents of tmp (which has the old
// stuff that was in *this) gets destructed
}
Note that you need a proper copy constructor for this to work, but given the Big 3 rule you already need a proper copy ctor.