Constructor cannot use make_shared<T>() - c++

I must be mistaken about something in the following code. I was experimenting, and couldn't understand why the make_shared cannot be called in the constructor, where as in initialize(), it works fine
class A {
public:
A() {
here = make_shared<A>();
}
void initialize(){
// here = make_shared<A>();
cout << &*here << endl;
cout << &here << endl;
}
void hereAddress() {
cout << &*here << endl;
}
private:
shared_ptr<A> here;
};
int main(){
vector<shared_ptr<A> > myA;
cout << "hi" << endl;
for (int i = 0; i < 10 ; ++i) {
myA.push_back(make_shared<A>() );
}
for (const auto& i : myA) {
i->initialize();
i->hereAddress();
}
return 0;
}
When I run this, I get exitcode -1. I appreicate your help.

This is because here = make_shared(); is invoking class constructor
and calling it inside constructor will make recursive calls to constructor causing segmentation faults
We need to call it outside constructor to avoid compiler complains.

Related

Is passing an r-value to functions returning it considered wrong in C++?

I want to create a function Service that energize an exhausted phone and return it as follows.
Writing
Phone p;
p = Service(p);
does not look elegant so I want to write as follows.
Phone& p = Service(Phone());
Doing so produces weird outputs as follows.
Ctor
Dtor
Destroyed
Energy: 100%
Ending...
The expected output is:
Ctor
Energy: 100%
Dtor
Destroyed
Ending...
Question
Could you tell me why this happens?
Note: I am new to C++.
class Phone
{
private:
int energy;
bool destroyed = false;
public:
Phone() : energy{ 0 } {
cout << "Ctor" << endl;
}
~Phone()
{
cout << "Dtor" << endl;
if (destroyed == false)
{
cout << "Destroyed..." << endl;
destroyed = true;
}
}
void Energize() { energy = 100; }
void Status() const
{
cout << "Energy: " << energy << "%" << endl;
}
};
Phone& Service(Phone&& input)
{
input.Energize();
return input;
}
int main()
{
Phone& p = Service(Phone());
p.Status();
cout << "Ending..." << endl;
}
It makes no sense to return a copy of the phone. So just pass it as reference and operate on it:
void Service(Phone& phone);
Phone p{};
Service(p);

Get space for array with malloc

Trying to pass pointer for array:
class aaa{
public:
int a ;
int b ;
std::string c ;
};
void abc(aaa* a [])
{
*a = (aaa*)malloc(sizeof(aaa)* 5);
a[0]->c ="ddd" ;
a[1]->c ="ccc" ; //crash
a[2]->c ="eee" ;
}
int main() {
aaa * a;
abc(&a);
cout << "!!!Hello World!!!"<< a++->c << endl;
cout << "!!!Hello World!!!"<< a++->c << endl;
return 0;
}
On second array element assignment I have crash. Where is the problem? Does malloc not creates enough space?
UPD.
I can't change function void abc(aaa* a []) signature because of some reason. It is not mistakable signature even it looks not nice.
I have updated program according recomendations in answers, but I still have crash in getting second array element member:
cout << "!!!Hello World!!!"<< a[1].c << endl;
Why? What I do wrong in code below?
struct aaa{
public:
int a ;
int b ;
std::string c ;
};
int abc(aaa* a [])
{
int asize =5;
*a = (aaa*)malloc(sizeof(aaa) * asize);
for (int i;i<asize;i++)
{
a[i] = new aaa();
}
a[0]->c ="ddd" ;
a[1]->c ="ccc" ;
a[2]->c ="eee" ;
return asize;
}
int main() {
aaa * a;
int asize=abc(&a);
cout << "!!!Hello World!!!"<< a[0].c << endl;
cout << "!!!Hello World!!!"<< a[1].c << endl; //crash
cout << "!!!Hello World!!!"<< a[2].c << endl;
for (int i=0; i<asize;i++)
{
cout << "free "<<i<<endl;
a[i].~aaa();
}
free(a);
cout << "end"<<endl;
return 0;
}
The problems are multifold:
mallocing non-POD types so their constructors don't run (catastrophic)
Failure to free the things you malloc (bad)
mallocing in C++ at all (not stylish)
Passing aaa* a[] when you meant aaa** a (valid but misleading)
No #includes, or namespace qualifier on cout and endl (invalid testcase)
Here's what your program should look like:
#include <vector>
#include <string>
#include <iostream>
class aaa
{
public:
int a;
int b;
std::string c;
};
std::vector<aaa> abc()
{
std::vector<aaa> result;
result.reserve(3);
result.push_back({0, 0, "ddd"});
result.push_back({0, 0, "ccc"});
result.push_back({0, 0, "eee"});
return result;
}
int main()
{
const auto a = abc();
std::cout << "!!!Hello World!!!"<< a[0].c << std::endl;
std::cout << "!!!Hello World!!!"<< a[1].c << std::endl;
std::cout << "!!!Hello World!!!"<< a[2].c << std::endl;
}
(Live demo)
Or, to keep your five up-front element allocations:
std::vector<aaa> abc()
{
std::vector<aaa> result(5);
result[0].c = "ddd";
result[1].c = "ccc";
result[2].c = "eee";
return result;
}
I strongly suggest forgetting everything you know about C, when you write C++.
You can use malloc, but you still need to call constructors, for this you need new, this defeats idea of using malloc.
const int asize = 5;
void abc(aaa*& a)
{
a = (aaa*)malloc(sizeof(aaa) * asize); // you need to release memory later
for (int i = 0; i < asize; ++i) {
new (a+i) aaa(); // you need to call constructors to intialize string
}
// now you can use strings
a[0].c = "ddd";
a[1].c = "ccc";
a[2].c = "eee";
}
int main() {
aaa * a;
abc(a);
cout << "!!!Hello World!!!" << a[0].c << endl;
cout << "!!!Hello World!!!" << a[1].c << endl;
// finally you need to call destructors
for (int i = 0; i < asize; ++i) {
a[i].~aaa();
}
free(a);
return 0;
}
After showing you how you can make it work, i would like to propose another solution. If you care about memory and don't want to use std::vector, you can use std::unique_ptr.
std::unique_ptr<aaa[]> data;
data = std::make_unique<aaa[]>(asize);
data[0].c = "text";
cout << data[0].c;
// no need to manually release memory
EDIT:
As of updated question. If you really want to pass array of pointers then you can do the following:
const int asize = 5;
void abc(aaa* a[]) {
// If array is really big, then you probably should preallocate memory and call placement new for every element.
for (int i = 0; i < asize; ++i) {
a[i] = new aaa; // again, you have to release memory
}
// now you can use strings
a[0]->c = "ddd";
a[1]->c = "ccc";
a[2]->c = "eee";
}
int main() {
aaa * a[asize];
abc(a);
cout << "!!!Hello World!!!" << a[0]->c << endl;
cout << "!!!Hello World!!!" << a[1]->c << endl;
for (int i = 0; i < asize; ++i) {
delete a[i];
}
return 0;
}
It would be very nice if you could use unique_ptr instead of raw pointer.

How to delete whole object by knowing only its base-pointer [duplicate]

This question already has answers here:
When to use virtual destructors?
(20 answers)
Closed 5 years ago.
I'm trying to implement autorelease pool in c++, and have trouble with deallocating.
So we have root-class object:
class object {
public:
object() {
retainCount_ = 0;
}
~object() {
std::cout << "object " << Description() << " is dealocated" << std::endl;
}
/* code with retain/release here */
int retainCount() {
return retainCount_;
}
std::string Description() {
std::stringstream ss;
ss << this;
return ss.str();
}
private:
int retainCount_;
};
And some realization:
class Integer : public object {
public:
int i;
Integer(int ii) : i(ii) {}
~Integer() {
std::cout << "Integer " << Description() << " is dealocated" << std::endl;
}
};
And of course release pool class, which works with root-class pointers:
class release_pool {
public:
void insert(object* obj) {
pointers_.insert(obj);
}
void flush() {
std::set<object*>::iterator it = pointers_.begin();
std::set<object*>::iterator tmp;
const int N = pointers_.size();
for (int i = 0; i < N; i++) {
tmp = it;
it++;
if ((*tmp)->retainCount() == 0 ) {
object* obj = *tmp;
std::cout << "delete obj: " << obj->Description() << std::endl;
pointers_.erase(tmp);
delete obj;
}
}
}
private:
std::set<object*> pointers_;
};
main.cpp code for test:
int main () {
release_pool pool;
Integer* obj = new Integer(5);
pool.insert(obj);
std::cout << "before flush: " << obj->i << "\n";
pool.flush();
std::cout << "after flush: " << obj->i << "\n";
return 0;
}
After build, I get next:
before flush: 5
delete obj: 0x7f9a84c025d0
object 0x7f9a84c025d0 is dealocated
after flush: 5
At the end: destructor of root-class is invoked, but of Integer not. Hence, we have leaked memory, which is allocated for Integer object. Have you any ideas to fix it? How i can delete whole object, not root-part of it.
You need to make your object destructor virtual.

How to be able to move data out of scope using default move constructor?

I want to move data into other scope. And it seems to work... yet destructor of an object seems to crush application with runtime exception:
#include <iostream>
using namespace std;
struct A {
void * data;
A() {
data = new char[10000];
std::cout << "A()" << std::endl;
}
~A() {
if(data != nullptr) {
delete [] ((char *)data);
std::cout << "Deleted Data!" << std::endl;
}
std::cout << "~A() " << std::endl;
}
};
void aDo2(A && a) {
cout << "Do2" << endl;
}
void aDo(A && a) {
cout << "Do" << endl;
aDo2(A(a));
}
int main() {
{
A a;
{
aDo(move(a));
}
cout << "why" << endl;
}
cout << "here?" << endl;
// your code goes here
return 0;
}
How to make move into other scope to work correctly?
When you allocate memory with the new[] operator you must free it with the delete[] operator, otherwise you will get undefined behavior (which is one of the most common reason behind crashes).
Also, when you move a pointer, you should clear the old pointer as it's not done automatically and can leave you with two (or more) objects with the sae pointer.

Error C2451 using boost::any

class A {
public:
void f()
{
cout << "A()" << endl;
}
};
class B {
public:
void f()
{
cout << "B()" << endl;
}
};
class C {
public:
void f()
{
cout << "C()" << endl;
}
};
void print(boost::any& a)
{
if(A* pA = boost::any_cast<A>(&a))
{
pA->f();
}
else if(B* pB = boost::any_cast<B>(&a))
{
pB->f();
}
else if(C* pC = boost::any_cast<C>(&a))
{
pC->f();
}
else if(string s = boost::any_cast<string>(a))
{
cout << s << endl;
}
else if(int i = boost::any_cast<int>(a))
{
cout << i << endl;
}
}
int main()
{
vector<boost::any> v;
v.push_back(A());
v.push_back(B());
v.push_back(C());
v.push_back(string("Hello boy"));
v.push_back(24);
for_each(v.begin(), v.end(), print);
}
I'm getting this error in print() when testing for string using Visual Studio 2010:
error C2451: conditional expression of type 'std::string' is illegal
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
else if(string s = boost::any_cast<string>(a))
This line is causing you problems. string s is not a pointer, it's a stack variable. You can't do a check for null.
The reason you can do a check on the integer below is that integers implicitly map to bool.
0 -> FALSE
1 -> TRUE
You shouldn't use any_cast on a reference here, because it throws a bad_any_cast exception if the type isn't right. Use a pointer in the last two cases like you did with the first three:
else if(string* s = boost::any_cast<string*>(&a))
{
cout << *s << endl;
}
else if(int* i = boost::any_cast<int*>(&a))
{
cout << *i << endl;
}