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
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);
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.
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.
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.
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;
}