Problem with Pointer Arithmetic using Classes - c++

I am experimenting with Pointers and can't figure out why this won't work.
I know that I am supposed to be using STL containers instead of using raw pointers but I am curious as to why this is not working.
Suppose that we have a class like this
class Example
{
public:
Example()
:number{10}
{
std::cout << "From Example Class " << std::endl;
}
~Example()
{
std::cout << "Destructor from Example Class" << std::endl;
}
void print()
{
std::cout << "Number from Example : " << number << std::endl;
}
private:
int number{};
};
We initialize a pointer to array of pointers like this
// Pointer to array of pointers
Example** ex_ptr_array{ new Example * [4] };
for (size_t i = 0; i < 4; i++)
{
ex_ptr_array[i] = new Example{};
}
I can dereference a pointer by doing this and I can call the objects method without using -> operator.
(*ex_ptr_array[0]).print();
// Prints Number from Example : 10
I can also use the array style and use -> operator to call the objects method.
ex_ptr_array[2]->print();
// Prints Number from Example : 10
But I dont understand why the Pointer Arithmetic will not work
// Why doesnt this work?
(*ex_ptr_array + 1)->print();
// Prints some random value
// Number from Example : -33686019

(*ex_ptr_array + 1)->print();
You're dereferencing ex_ptr-array first, and then adding one. Do it the arithmetic before the dereference:
(*(ex_ptr_array + 1))->print();
The compiler knows the size of the type held in ex_ptr_array, so when you add 1 to the pointer, it actually increments the pointer by the size of that type.

Related

How to compare two objects by class name or type (equivalent of Java's `getClass()` in C++)

I'd like to compare two objects by their class name. The first object is of type Card* which points to a MagicCard object, and the second is of type MagicCard - a child class of Card. When I compare them with typeid it doesn't work:
if (typeid(*(this->cards[index])) != typeid(card)) {
//the first object is of type Card* inside a vector and points to a
MagicCard object
//card is of type MagicCard
return false;
//this "if" check stops the method in case the types are different.
}
The comparison above should return that the objects are of the same type, because the the element in that position inside the vector I know that there is a function getClass() in Java so I am looking for some kind of an equivalent in C++ which compares objects by the derived class, not by the mother class.
EDIT: I changed the code to Peter's suggestion and added information why I need this check. It doesn't work yet.
It's almost always incorrect to be looking at typeid.
You can get a MagicCard * from a Card * with dynamic_cast, and it will be a null pointer if the Card * doesn't point to a MagicCard object.
if (auto * magicCard = dynamic_cast<MagicCard>(cards[index])) {
// do something with magicCard
}
However it is often better to add virtual void doSomething() to Card, and override it in MagicCard.
cards[index]->doSomething(); // no mention of MagicCard needed
It is not clear how your Card and MagicCard classes are declared.
typeid does not work with non-polimorphistic classes according to cppreference.com.
If you, for example got the following program, the output will be as shown in the comments next to the output line:
#include <iostream>
#include <typeinfo>
class BaseNonPoly { };
class DerivedNonPoly : public BaseNonPoly { };
class BasePoly { virtual void foo() {} };
class DerivedPoly : public BasePoly { };
int main()
{
BaseNonPoly baseNonPoly;
DerivedNonPoly derivedNonPoly;
BasePoly basePoly;
DerivedPoly derivedPoly;
BaseNonPoly& pBaseNonPoly = baseNonPoly;
BaseNonPoly& pDerivedNonPoly = derivedNonPoly;
BasePoly& pBasePoly = basePoly;
BasePoly& pDerivedPoly = derivedPoly;
std::cout << "typeid(baseNonPoly)=" << typeid(baseNonPoly).name() << std::endl; // typeid(baseNonPoly)=11BaseNonPoly
std::cout << "typeid(derivedNonPoly)=" << typeid(derivedNonPoly).name() << std::endl; // typeid(derivedNonPoly)=14DerivedNonPoly
std::cout << "typeid(basePoly)=" << typeid(basePoly).name() << std::endl; // typeid(basePoly)=8BasePoly
std::cout << "typeid(derivedPoly)=" << typeid(derivedPoly).name() << std::endl; // typeid(derivedPoly)=11DerivedPoly
std::cout << "typeid(pBaseNonPoly)=" << typeid(pBaseNonPoly).name() << std::endl; // typeid(pBaseNonPoly)=11BaseNonPoly
std::cout << "typeid(pDerivedNonPoly)=" << typeid(pDerivedNonPoly).name() << std::endl; // typeid(pDerivedNonPoly)=11BaseNonPoly
std::cout << "typeid(pBasePoly)=" << typeid(pBasePoly).name() << std::endl; // typeid(pBasePoly)=8BasePoly
std::cout << "typeid(pDerivedPoly)=" << typeid(pDerivedPoly).name() << std::endl; // typeid(pDerivedPoly)=11DerivedPoly
return 0;
}
As you can see, the object of the non-polimorphic derived class DerivedNonPoly without virtual method can not be identified as what it really is and returns the type of it's parent BaseNonPoly instead.
As in Caleth's answer mentioned, it is good practice to avoid special cases depending on concrete derived class types. Since this, however, can't always be avoided in an elegant way, it might be enough to use a unused virtual function or a virtual deconstructor to your Card and MagicCard class for typeid to work correctly.

What is a pointer of int data type pointing at if is a private data member of a class and we create two objects of that class?

I have a class for a sparse matrix. Say it has a pointer a of int data type as a private data member. My question then is, if I create two objects B and C of that class, would both B and C have a pointer a pointing to the same location or they would do something else?
I am confused here.
The actual pointer in my class is defined as a private member thus:
element* ele;
and it's assigned in the constructor with:
ele = new element[this->num_non_zero];
Now that we can see the code you're discussing, the pointer you have is declared and initialised (in the constructor) in the following manner:
Element *ele;
ele = new element[this->num_non_zero];
That use of new gives each instance their own copy of memory to which their own ele variable points to. There is no possibility of different instances interfering with each other given this method.
Below is the original answer, before you added the deail allowing us to succinctly answer your question. Since it provides interesting background information, I've left it in.
Unless the member variable is a class-level static (shared amongst all instances of the class), it belongs to the instance itself, and will point to wherever it's set to (possibly, but not necessarily, in a constructor).
See, for example, the following code, which has both a static and non-static member variable:
#include <iostream>
#include <string>
class demo {
public:
demo(int newnonstat = 7, int newstat= 42): nonstat(newnonstat) {
std::cout << "create\n";
stat = newstat;
}
void dump(std::string desc) {
std::cout << desc << ": " << nonstat << ' ' << stat << '\n';
}
private:
int nonstat;
static int stat;
};
int demo::stat;
int main() {
demo d1; d1.dump("d1");
demo d2(1, 2); d2.dump("d2"); d1.dump("d1");
}
The output of that shows that the possibilities for how the two types are set (with my added comment):
create
d1: 7 42
create
d2: 1 2
d1: 7 2 <-- "corrupted" static
So, unless they're static, the variables will be distinct. However, as pointers, there's nothing that stops distinct pointers pointing to the same thing, it all comes down to what the various bits of code set it to.
Another example, with distinct pointers that point to the same thing:
#include <iostream>
#include <string>
class demo {
public:
demo(char *pStr) : m_pStr(pStr) {}
void dump(std::string desc) {
std::cout << desc << ": " << &m_pStr << ' ' << (void*)m_pStr << " '" << m_pStr << "'\n";
}
private:
char *m_pStr;
};
int main() {
char buff[] = "same string";
demo d1(buff);
demo d2(buff);
d1.dump("d1");
d2.dump("d2");
}
The output shows the pointers, although distinct (second column is address of pointer variable), pointing to the same thing (third and fourth column):
d1: 0x7ffea260c150 0x7ffea260c18c 'same string'
d2: 0x7ffea260c158 0x7ffea260c18c 'same string'

Why when i try to print a map content i get the adresses not the value ? in c++

I have a class Servicii that is empty and 2 classes Car and Book(I will use later for renting more types of services) that extends this class. Also I have another class Person .
After that I declared a map std::map<Person*,Servicii*> servicii; and this function:
template<class T>
void rentService(Person *p,T service)
{
if (typeid(*service).name() == typeid(Car).name()) {
if(p->checkDriverLicense()==true)
{
std::cout<<"Name:"<<p->getName()<<std::endl;
servicii.insert(std::make_pair(p,service));
}
}
}
In main I've created some object :
Car *c1=new Car("Skoda",150,true,"red",2014);
Person *p1=new Person("Ale",22);
rentService(p1,c1);
print(servicii);
and the print function :
void print(std::map<Person*,Servicii*> m) {
for(auto const &it: m) {
std::cout << "[" << it.first << "," << it.second << "]" << std::endl;
}
}
When I compile this is what it's printed :
Name:Ale
[0x1ba840,0x1ba4b8]
Why there in the map I have addresses?
Why there in the map i have adresses ???
Because that's what you stored in the map. The types that you specified for key and value are Person* and Servicii* respectively. Both of types are pointers. A pointer stores a memory address.
When you insert a pointer into a character stream, it will be printed as a hexadecimal number (except for pointer to char, which is treated differently).
Car *c1=new Car("Skoda",150,true,"red",2014);
Don't use bare owning pointers. Either use smart pointers, or store as an element of a container. For example in this case, std::map<Person,Servicii> might be appropriate.
You need to dereference the pointers:
void print(std::map<Person*,Servicii*> m) {
for(auto const &it: m) {
std::cout << "[" << *(it.first) << "," << *(it.second) << "]" << std::endl;
}
}
Make sure that you've implemented operator<< for Person and Servivii.
You are printing the pointer itself, which is an address.
what you need is the to dereference the pointer.
for example:
std::cout << it.first->getName() << "\n";
Direct answer:
Since your map's key value pairs are pointers and the pointers are addresses which point to a address, when you are printing pointers you get a hexadecimal value which represent the address of the pointer
Recommendation:
If you want to print customized information , what you can do is overload << operator for each class to print information you expect.
class Person {
public:
ostream& operator<<(ostream& os, Person const& person) {
return os << "I am " << person.m_name << " " << person.m_surname << endl;
}
private:
string m_name;
string m_surname;
};
If you store relatively lower size objects (you need to make a decision considering the hardware and software requirements) just store objects instead of pointers in map.
Easily maintainable way of pointers are smart pointer, Therefore give it a try to use them instead of raw pointers.

Is calling std::fill() before std::erase() produces undefined behaviour?

I'm working on a C++11 program, where security is important and my task is to set to 0 the used memory after erasing it.
I have an std::map mapping from int to an std::vector of pointer to class. I have the index in std::map and a pointer to the instance I would like to delete.
The following code produces the output I want, however, I'm not sure if it's good formed code (or I would say I'm not sure if this code is ok or not).
I have 2 questions.
If the following code is ok,
It can only be compiled with -fpermissive, I don't understand the compiler error message.
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
class MyClass
{
private:
int num;
public:
MyClass(int num) { this->num = num; }
int GetNum() const { return this->num; }
};
void PrintWorkingData(const std::map<int, std::vector<MyClass*>>& working_data, int idx)
{
std::cout << "working_data[" << idx << "] is an std::vector, size: " << working_data[idx].size() << ", containing the following items: " << std::endl;
for (std::vector<MyClass*>::const_iterator it = working_data[idx].begin(); it != working_data[idx].end(); it++)
{
std::cout << "(*it)->GetNum() = " << (*it)->GetNum() << std::endl;
}
}
int main()
{
MyClass* DeleteMyClass;
std::map<int, std::vector<MyClass*>> working_data;
working_data[0].push_back(new MyClass{4});
working_data[0].push_back(new MyClass{7});
working_data[1].push_back(new MyClass{11});
// the origonal code isn't like this; let's suppose
// we stored in the DeleteMyClass pointer the MyClass pointer
// that we would like to delete
working_data[1].push_back(DeleteMyClass = new MyClass{22});
working_data[1].push_back(new MyClass{33});
working_data[2].push_back(new MyClass{1000});
PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);
// so our task is to delete DeleteMyClass object from working_data[DeleteItemIndex]
// and fill with 0 where it was stored
int DeleteItemIndex = 1;
std::vector<MyClass*>::iterator pos = std::find(working_data[DeleteItemIndex].begin(), working_data[DeleteItemIndex].end(), DeleteMyClass);
if (pos == working_data[DeleteItemIndex].end())
{
std::cout << "Error: The item does not present in the working_data" << std::endl;
}
else
{
std::fill(pos, pos + 1, 0);
working_data[DeleteItemIndex].erase(pos);
delete DeleteMyClass;
std::cout << "The object successfully deleted" << std::endl;
}
PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);
return 0;
}
Setting a pointer value to nullptr doesn't change the data it points to. Erasing an element from a vector will overwrite that element with all the later ones in the vector, leaving (in this case) a second pointer in allocated memory (beyond the size of the vector) to the last element in the vector.
To erase the memory occupied by the object that DeleteMyClass points to, you'll have to handle the object destruction and memory freeing separately. This is not necessarily easy or straightforward, as there can be nuances (exception handling, array vs. non-array forms) that need to be addressed. You should also keep in mind that it is possible to inspect the memory of a running process, and view the data you're trying to erase while the object that uses it is live.
Here are several approaches that might work for you case.
One way to do this is to manually call the destructor, clear out the memory, then free it.
DeleteMyClass->~MyClass();
memset(DeleteMyClass, 0, sizeof(*DeleteMyClass));
delete (void *) DeleteMyClass;
The cast on the delete call is necessary to avoid calling the destructor, and the number of bytes to clear uses the type of DeleteMyClass, which will be incorrect if what is pointed to is a class derived from MyClass.
Another alternative is to use placement new with an already allocated memory buffer and a custom deallocator (after manually calling the destructor) to free up the memory.
A third possibility is to use custom new and delete functions, either for this specific class or globally.

Does calling the constructor of an empty class actually use any memory?

Suppose I have a class like
class Empty{
Empty(int a){ cout << a; }
}
And then I invoke it using
int main(){
Empty(2);
return 0;
}
Will this cause any memory to be allocated on the stack for the creation of an "Empty" object? Obviously, the arguments need to be pushed onto the stack, but I don't want to incur any extra overhead. Basically I am using the constructor as a static member.
The reason I want to do this is because of templates. The actual code looks like
template <int which>
class FuncName{
template <class T>
FuncName(const T &value){
if(which == 1){
// specific behavior
}else if(which == 2){
// other specific behavior
}
}
};
which allows me to write something like
int main(){
int a = 1;
FuncName<1>(a);
}
so that I get to specialize one template parameter, while not having to specify the type of T. Also, I am hoping the compiler will optimize the other branches away inside the constructor. If anyone knows if this is true or how to check, that would be greatly appreciated. I assumed also that throwing templates into the situation does not change the "empty class" problem from above, is that right?
Quoting Stroustrup:
Why is the size of an empty class not zero?
To ensure that the addresses of two different objects will be different. For the same reason, "new" always returns pointers to distinct objects. Consider:
class Empty { };
void f()
{
Empty a, b;
if (&a == &b) cout << "impossible: report error to compiler supplier";
Empty* p1 = new Empty;
Empty* p2 = new Empty;
if (p1 == p2) cout << "impossible: report error to compiler supplier";
}
There is an interesting rule that says that an empty base class need not be represented by a separate byte:
struct X : Empty {
int a;
// ...
};
void f(X* p)
{
void* p1 = p;
void* p2 = &p->a;
if (p1 == p2) cout << "nice: good optimizer";
}
This optimization is safe and can be most useful. It allows a programmer to use empty classes to represent very simple concepts without overhead. Some current compilers provide this "empty base class optimization".
It might, it might, not, depending on circumstances. If you say:
Empty e;
Empty * ep = & e;
then obviously things have to be allocated.
Try it and see. Many compilers will eliminate such temporary objects when asked to optimise their output.
If the disassembly is too complex, then create two functions with different numbers of such objects and see if there is any difference in the stack locations of objects surrounding them, something like:
void empty1 ( int x )
{
using namespace std;
int a;
Empty e1 ( x );
int b;
cout << endl;
cout << "empty1" << endl;
cout << hex << int ( &x ) << " " << dec << ( &x - &a ) << endl;
cout << hex << int ( &a ) << " " << dec << ( &a - &b ) << endl;
}
and then try running that compared with an empty8 function with eight Empties created. With g++ on x86, if you do take the address of any of the empties you get a location between x and a on the stack, hence including x in the output. You can't assume that the storage for objects will end up in the same order as they are declared in the source code.