I am learning C++ and I can not figure this out. I do not want to post all my code but feel that it is necessary as it is overall short.
#include <iostream>
#include "MathObject.h"
using namespace std;
int main(int args, char *argv[]){
MathObject mo = new MathObject(3,4);
int sum = mo.sum();
cout << sum << endl;
return 0;
}
#include <iostream>
#include "MathObject.h"
using namespace std;
MathObject :: MathObject(int n, int m){
num1 = n;
num2 = m;
}
int MathObject :: sum(){
return num1+num2;
}
class MathObject{
private:
int num1;
int num2;
public:
int sum();
MathObject(int n, int m);
};
So this is all in 3 separate files, I am using an example from my prof as a template on how to make classes and header files to organize our code. This always returns the error:
conversion from 'MathObject*' to non-scalar type 'MathObject' requested| ||=== Build finished: 1 errors, 0 warnings (0 minutes, 0 seconds) ===|
I have been going over the code for a while now but I can not get it! If anyone can point out what is wrong I would love to hear.
Thanks!
In C++ you can just make an object on the stack:
MathObject mo(3,4);
This statement creates a MathObject called mo on the stack, that will be automatically destroyed when main returns. This should be your preferred way of creating objects.
The new operator in C++, unlike the new operator in Java or C#, is not needed for creating an object and should generally be used very sparingly. It allocates memory from the heap for holding the object, which allows the object's lifetime to extend beyond the current function. But that also means that you are responsible for cleaning up with delete after you are done using the object, or the memory will be leaked.
MathObject *mo = new MathObject(3,4); // Never do this!
This is terrible code. It's a) inefficient (allocating from the heap with new is much more expensive than the stack) and b) unsafe, because if for some reason you fail to delete mo; (sometimes the reason is out of your control, such as an exception being thrown through your code) the memory is leaked.
std::unique_ptr<MathObject> mo(new MathObject(3,4));
This uses new to create a MathObject object on the heap, and stores the returned pointer in a unique_ptr object created on the stack. The unique_ptr object will automatically delete the pointer stored in it when the unique_ptr is destroyed. This is safe, but it's still much slower than the first version.
Your declaration of MathObject is faulty. If you are dynamically allocating a MathObject, it should be
MathObject * mo = new MathObject(3,4);
And the sum function should be called using -> operator like this:
int sum = mo->sum();
Or if you want to create an object on the stack, you should not be using the new operator.
MathObject mo(3,4);
int sum = mo.sum();
That will do the trick.
Edit:
Here is how it works on the top level:
The new operator searches for the free memory for your object (In your case that is a MathObject), and initializes a new object in the space using the constructor arguments you passed. Then, it returns a pointer to this newly created object. So on the lhs, you should be declaring a pointer that can point to a MathObject. That is why we have MathObject * mo and not Mathobject mo.
I hope that helps!
the way you are creating a new object is how you would do it in C# or Java.
in C++ it is better to avoid using new because you will have to keep memory management in mind and also it is much slower.
the little piece of code shows you how to use constructors:
#include <iostream>
using std::cout;
using std::endl;
class MathObject{
public:
MathObject (){
cout<<"Calling Default constructor"<<endl;
}
MathObject (int i, int j){
x = i;
y = j;
cout<<"Calling constructors with two parameters"<<endl;
}
private:
int x, y;
};
int main () {
MathObject mo;
MathObject mo2(3,4);
}
output:
Calling Default constructor
Calling constructors with two parameters
It's your object initalisation, here:
MathObject mo = new MathObject(3,4);
You create a local object mo, then you you create another object somewhere on the heap and new returns a pointer to it. So your compiler understands that you want to assign a pointer to mo.
Replace your line with:
MathObject mo = MathObject(3,4);
or even:
MathObject mo(3,4);
Please note that these two forms give in fact the same result: in both case, the compiler generates only one object and one call to the constructor with the parameter(3,4), despite the "=" operator. To know more about this, look at: http://www.gotw.ca/gotw/001.htm .
Related
I have a class called Myclass. In the main function, I have created an array object for this class. Whenever I try to delete this dynamically allocated array, the visual studio will say, Error: Debug Assertion Failed!. Expression: is_block_type_valid(header->_block_use). Can you please tell me what is causing this or show me an example of fixing this issue.
#include <iostream>
using namespace std;
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
// Call each object's print function.
for (int index=0; index < 3; index++)
{
obj[index]->print();
}
delete[] obj; //Error
return 0;
}
This:
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
is not a dynamically allocated array. It is an array with automatic storage, holding pointers to dynamically allocated objects. To properly clean up, you need:
delete obj[0];
delete obj[1];
delete obj[2];
Because every new must be matched with a delete, and you can only delete via delete[] something that was allocated via new[].
There is no need for any dynamic allocation here, just do:
Myclass obj[3] = {};
The delete[] operator should only be used for arrays created using the new[] operator, which your obj isn't. You have a fixed array of pointers to objects, each of which must be deleted as such:
for (int index=0; index < 3; index++)
{
delete obj[index];
}
Alternatively, you can create your object array using the new[] operator, then delete the array with delete[]:
int main()
{
Myclass* obj = new Myclass[3];
// Call each object's print function.
for (int index = 0; index < 3; index++) {
obj[index].print(); // Note: Use "." here, not "->"
}
delete[] obj;
return 0;
}
The variable obj is declared as an array with automatic storage duration with the element type Myclass *.
Myclass *obj[3] = { new Myclass, new Myclass, new Myclass };
That is it is an array of pointers not a pointer.
Each element of the array is indeed a pointer that points to a dynamically allocated memory. So as the array contains three elements you need to call the operator delete three times for each element.
It is simpler to do that in the range-based for loop.
For example
for ( auto &item : obj )
{
delete item;
item = nullptr;
}
I think you allocated the array wrong.
You should write Myclass* obj = new Myclass[3];
The above answer is perfect.
I would only add this is not a good style code, if you "think in C++". This is a rather C style code.
First of all, when you are coding in C++ and is not obligued to use C-compatible code, be cautious whenever you see yourself using a C pointer.
In this case, if instead of using a C array of C pointers, you had used a std::vector of MyClass objects, the vector destructor would have called your class destructor for each element, which I think is what you wanted.
My suggestion: change the C array to std::vector and you will be happier. Look how you could have implemented it, using C++11 features and forgetting old C stuff:
#include <iostream>
using namespace std;
#include <vector>
class Myclass
{
public:
void print()
{
cout << "Hello from Myclass" << endl;
}
};
int main()
{
cout<<"Hello World" << endl;
vector<Myclass> obj(3);
// Call each object's print function.
for (auto instance : obj)
{
instance.print();
}
return 0;
}
In this case you don't even need to worry about deleting the objects, since the vector destructor will be called when the function goes out of scope, and it will take care of calling Myobjects' destructors. Much cleaner and safer code.
Or, in case performance is a very bottleneck for you and you need a static array, if you are using C++11 or later, you also can use std::array, a less "wild" option (https://en.cppreference.com/w/cpp/container/array).
So that is the tip I leave for you, if coding in C++, use the best this language can offer, and try to forget dangerous and wild old C features. C is good as a lightweight and simpler language, when you need it. But everyone knows it is dangerous (and you have just stumbled on it).
This book of the Bjarne focuses on teaching C++ from scratch, leaving behind the not always productive C legacy:
Programming: Principles and Practice Using C++
I have two classes one is main and other is Test, for the Test class, I have Test.cpp and Test.h
//-----Test.h--------//
#pragma once
class Test
{
private:
int num;
public:
Test(void);
Test(int n);
~Test(void);
};
//------Test.cpp------//
#include "Test.h"
#include<iostream>
using namespace std;
Test::Test(void)
{
}
Test::Test(int n)
{
num = n;
}
Test::~Test(void)
{
cout << "Deleted" << endl;
cout << "num = " << num << endl ;
}
//---------main.cpp--------------//
#include "Test.h"
#include<iostream>
using namespace std;
int main()
{
Test t1 = Test(5);
return 0;
}
The output which I have expected is
Deleted
num = 0
But Real Output is
Deleted
num = 5
Why this occurs, why destructor, dint free the memory
or dint delete the basic data type, How can I delete the variable,
Using what method I can observe basic datatype getting deleted?
Destruction of an object does not mean setting values to zero. That would be unnecessary work. Rather, all that is required is that resources be released. Bits are typically left as-is (representing 5 in your example) unless there is a compelling reason to do otherwise.
Furthermore, members are destroyed after the class. In your example, first ~Test() is run to destroy t1, then t1.num would be destroyed. The destructor of Test cannot view the destruction of Test::num.
why destructor, dint free the memory or dint delete the basic data type
You did not have any memory allocated in the heap, so there is no need to free anything.
All you have is a basic type int which does not need any memory deallocation.
If instead you had some pointer member variable:
private:
int* num;
and you allocated it somewhere in your constructor: new int(6); then sure you must deallocate/free it inside your destructor.
In this case, probably a shared-pointer may help, which automatically is destroyed just after the destructor:
std::shared_ptr<int> num;
But it has to be constructed, in the constructor you need:
Test::Test(int n)
: num(std::make_shared<int>(n)
{
// *n == 100
}
To see if the data is deleted use Valgrind.
#include <iostream>
#include "QueueAr.h"
class Test {
int val;
public:
Test(int v)
{val = v;};
int getVal()
{return val;};
};
using namespace std;
int main(int argc, char **argv)
{
Queue<Test*> testStack(4);
for(int i = 0; i < 4; i++) {
Test *t = new Test(5);
testStack.enqueue(t);
delete t;
}
while(!testStack.isEmpty())
cout << (testStack.dequeue())->getVal() << endl;
return 0;
}
So I'm trying to play with the idea of declaring a template class with a data type that is programmer-defined. I decided to go a queue implementation made by the author of my data structures book as the template class.
Now I'm trying to feed some values into it.
I started by creating a Queue object whose data type is a pointer variable to my own class Test. I used a pointer variable because Queue<Test> wasn't working properly for some reason. Next, I came up with the above for loop to make an attempt at initializing, but when I dequeue and display the values, it returns all of them as zero, despite sending 5 to Test's constructor four times in the loop. I believe it might have something to do with the loop, or Test*, but I'm not entirely sure.
Does anyone know what might be wrong here? Thank you in advance.
Also, if anyone needs it, here are the links for the header file "QueueAr.h" and its member functions
https://github.com/rweichler/ecs60/blob/master/p2/src/QueueAr.h
https://github.com/rweichler/ecs60/blob/master/p2/src/QueueAr.cpp
After storing the pointer to Test in your Queue you delete the pointer. This frees the memory and leaves the pointer stored in the Queue dangling, pointing at freed memory. When you dereference this pointer to display the value you can get anything.
I'm a c++ student and this is my second post here. I'm working on a class whose job is to maintain an array of object pointers. (That way a pointer can be passed in and added to the array, instead of the entire object.)
The array is supposed to be dynamic but I'm running into some errors when I try to dynamically allocate memory for it. The following code produces the error "expression must be a modifiable lvalue" at studArray, as marked.
#ifndef MYCLASS_H
#define MYCLASS_H
#include "Student.h"
class myClass{
private:
Student* studArray[5];
int howMany;
int max;
public:
myClass(){
Student firstOne;
studArray[0] = &firstOne;
howMany=0;
max=5;
}//myClass()
void insertEl( Student* nextEl ){
howMany++;
if(howMany >= max){
Student** tempPt = new Student* [max + 1];
for( int i = 0; i < currentNum; i++){
tempPt[i] = studArray[i];
}
delete [] studArray;
studArray = tempPt; // <-------------------------error
}
studArray[ howMany ] = nextEl;
}//insertEl
};
I tried changing the original Student * array to have no size specified, but that produced the error "incomplete type is not allowed" at studArray.
class myClass{
private:
Student* studArray[]; <------------- error
int howMany;
int max;
What am I doing wrong?
(Thank you for the help!)
For reference I'm using Win 7 64bit, Visual Studio Professional 2012.
Assumptions: Instructor want you to learn the fine art of memory management on your own. So no library containers and no smart pointers. When you have the time, look into how to use the standard containers and the smart pointers. They'll save you a huge amount of time and grief in the future.
First, declaring the Student array.
Student* studArray[5];
You have the crux of it right here
Student** tempPt = new Student* [max + 1];
So try
Student** studArray;
And then hack your constructor to allocate the storage
myClass()
{
max = 5;
studArray = new Student*[max]; /* For improved safety, read up on
exceptions, catch and handle the
out of memory exception */
howMany = 0;
} //myClass()
I recommend adding a destructor to handle the clean up and put back your array.
virtual ~myClass()
{
delete[] studArray;
}
Check with the assignment notes or the instructor to see who is responsible maintaining the Students. You may have to revisit the destructor to delete all of the Students before deleting studArray
Additional note:
myClass()
{
Student firstOne;
studArray[0] = &firstOne;
howMany=0;
max=5;
}//myClass()
Student firstOne; is a temporary variable. firstOne only exists between the closest enclosing {} braces. This is called Scope. Using any value outside of it's scope will have unpredictable results and most likely crash the program. Frankly, that's if you are lucky. The program may limp on for some indeterminate time and crash later.
The assignment studArray[0] = &firstOne; is dangerous because by the time anyone tries to use studArray[0], the data at which it points will not be valid. firstOnedoes not exist outside the constructor. If you want firstOne to go on living, you will have to define it as a pointer, create it with new, and delete it when it is no longer needed. In this case I don't think you ever need it.
Another suggestion is to double the size of studArray rather then simply adding one when it is full. This way you don't have to reallocate the storage and copy all of the existing students to the new storage as often.
A better method is to have a std::vector of Student:
std::vector<Student *> maleStuds;
std::vector<Student *> femaleStuds;
Or, if you must use arrays:
const unsigned int MAXIMUM_STUDENTS = 5;
Student * students[MAXIMUM_STUDENTS];
For dynamic:
Student * * students = new Student * [MAXIMUM_STUDENTS];
Hi iam new to c++ and iam trying out this vector program and i am getting the following error:
error: conversion from test*' to non-scalar typetest' requested|
Here is the code
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
class test{
string s;
vector <string> v;
public:
void read(){
ifstream in ("c://test.txt");
while(getline(in,s))
{
v.push_back(s);
}
for(int i=0;i<v.size();i++)
{
cout<<v[i]<<"\n";
}
}
};
int main()
{
cout<<"Opening the file to read and displaying on the screen"<<endl;
test t=new test();
t.read();
}
new is used to dynamically allocate memory. You don't need to do that, so just do:
test t; // create an instance of test with automatic storage
t.read(); // invoke a method
The error is because the type of new test() is a test*, a pointer to a (newly created) test. You can't assign a test* to a test.
The pointer version, for what it's worth, would have been:
test* t = new test();
t->read(); // the arrow is short for (*test).
delete t; // don't forget to clean up!
However, it's bad style to do raw memory allocation like that. You'd use something called a smart pointer to make sure it gets deleted automatically, instead. The standard library has one in the header <memory>, called auto_ptr, that would suffice:
std::auto_ptr<test> t(new test()); // put a new test into a pointer wrapper
t->read(); // treat it like a normal pointer
// nothing else to worry about, will be deleted automatically
However, all this isn't needed for you, in this case. Always prefer automatic (stack) allocation over dynamic allocation.
Change
test t=new test();
t.read();
to
test *t=new test();
t->read();
t should be a pointer to type test. And to access a class member using a pointer we use the -> operator. Also its a good practice to delete any dynamically allocated objects as:
delete t;
new test() will return a pointer to a t so you either want to use pointer throuought or create t on the stack
Code using pointers
test *t=new test();
t->read(); // note needs -> rather than .
delete t; // as declared n the heap you must delete
or usually better do all on the stack
test t;
t.read();