Why is the scope of object created using new limited? [duplicate] - c++

This question already has answers here:
Do Pointer Parameters Need To Be Passed By Reference
(3 answers)
Closed 3 years ago.
Object made using new operator does not seem to be available outside the scope! Isn't that the whole point of the new operator?
https://ideone.com/DDvo9y - Please check this link to see the result.
#include<iostream>
class myClass
{
private:
int val;
public:
myClass () = delete;
myClass (int val):val{val}{}
int get () const
{
return val;
}
};
bool ifEqualMake (int a, int b, myClass * obj)
{
if (a == b) obj = new myClass (a);
else{
std::cout << "Difference exists: " << a - b << '\n';
obj = new myClass (a + b);
}
std::cout << " Object made with value :" << obj->get () << '\n';
return (a == b);
}
int main ()
{
myClass *obj1 = nullptr;
myClass *obj2 = nullptr;
myClass *obj3 = nullptr;
ifEqualMake (3, 3, obj1);
ifEqualMake (4, 3, obj2);
ifEqualMake (4, 4, obj3);
if(obj1) std::cout << "obj 1 made in heap: " << obj1->get () << '\n';
if(obj2) std::cout << "obj 2 made in heap: " << obj2->get()<<'\n';
if(obj3) std::cout << "obj 3 made in heap: " << obj3->get () << '\n';
delete obj1;
delete obj2;
delete obj3;
return 0;
}

It isn't.
You're confusing the dynamically-allocated object that you created with new, and the pointer that points to it.
The pointer's scope is limited just like any other automatic-storage-duration object.
It looks like you meant to use it as an "out" argument to the function ifEqualMake, perhaps by taking a reference to it rather than a copy. Then alterations to it, such as pointing it to a new object, will be mirrored in the calling scope.

The parameter obj is passed by value, that means it's just a copy of the argument, and any modification on itself inside the function (like obj = new myClass (a);) has nothing to do with the original pointer. In the meanwhile, the object constructed inside the function won't be destroyed.
You might change it to pass-by-reference.
bool
ifEqualMake (int a, int b, myClass *& obj)
// ^
{
...
}

Consider the following function:
void foo(int i) {
i = 4;
}
void bar() {
int j = 0;
foo(j);
std::cout << j << '\n';
}
You would expect bar to print 0, not 4, because foo is assigning to a local variable.
This behaviour does not change with pointers. The following code behaves the same way:
void foo(int* i) {
int temp = 0;
i = &temp;
}
void bar() {
int* j = nullptr;
foo(j);
std::cout << j << '\n';
}
The simplest fix to the code you present is to take the pointer by reference:
void foo(int*& i) {
int temp = 0;
i = &temp;
}
void bar() {
int* j = nullptr;
foo(j);
// j now points to a destroyed object
std::cout << j << '\n';
}

Related

C++ How do I return an object containing a pointer without triggering the destructor?

code looks like this
#include<iostream>
class A
{
public:
int* a;
char name;
A(char _n = 'N')
{
a = 0;
name = _n;
}
A(int _a, int _b, char _n = 'N')
{
name = _n;
a = new int[2]{ _a, _b };
}
~A()
{
std::cout << "deleting object..." << name << "\n";
delete[] a;
}
//
void operator=(A b)
{
std::cout << "cleanup begin\n";
delete[] a;
a = new int[] {b.a[0], b.a[1]};
}
//
A Copy()
{
if (a == 0) return *new A();
A* _r = new A(a[0], a[1], name + 1);
return *_r;
}
};
//
int main()
{
A d{0, 1, 'T'};
{
A Z(0, 1);
Z = Z.Copy();
}
std::cout << "check\n";
return 0;
}
I want Z = Z.Copy() to work but instead it triggers a breakpoint in delete_scalar.
From what i understand, the overloaded = should free the memory that is allocated to member a, after which it should allocate new memory and copy the integers by value, then destroying b.
Even so, object Z from the nameless scope has its destructor called twice, leading to the breakpoint trigger.
All that I want is to be able to do something like this:
x = (x - y) * z + y;
where I can overload = for x to assign to it the result of overloaded object operations (x and y are custom vector3 instances, z is a custom Matrix4 instance, Matrix4 contains a float*, if that's relevant).
So, what is the problem and how do I solve it?

How do you call a function from a pointer array to a class method in C++? [duplicate]

This question already has answers here:
C++ Call Pointer To Member Function
(4 answers)
Closed 1 year ago.
I'm pretty new to C++
I have this code:
in my class.hpp
class Dummy {
private:
void f1(void);
void f2(void);
void f3(void);
void f4(void);
public:
void caller(std::string id);
};
in my class.cpp
void Dummy::caller( std::string id ) {
// something something about qualifiers requires Dummy::*f instead of just *f
void (Dummy::*f[4])() = {&Dummy::f1, &Dummy::f2, &Dummy::f3, &Dummy::f4};
string v[4] = {"f1", "f2", "f3", "f4"};
for (int i = 0; i < 4; i++) {
if (id == v[i]) {
(*f[i])();
break ;
}
}
}
this (*f[i])() is valid in C code, but for some reason in C++, it shows me this error which i googled but was unlucky and found nothing that useful, except for std::invoke which is in C++17 (?), and I'm bound to C++98
The error:
Class.cpp:41:5: error: indirection requires pointer operand ('void (Dummy::*)()' invalid)
(*f[i])();
^~~~~
well, this is not how c++ works...
just because you define functions like
void f1(void);
void f2(void);
void f3(void);
void f4(void);
doesnt mean you can access them or handle then like you were working with an array
but that is the key to solve that,
you can create an array of functions and call it by index
here is a short example of how you can achieve that:
#include <iostream>
void f1(void)
{
std::cout << "you are in f1" << std::endl;
}
void f2(void)
{
std::cout << "you are in f2" << std::endl;
}
void f3(void)
{
std::cout << "you are in f3" << std::endl;
}
void f4(void)
{
std::cout << "you are in f4" << std::endl;
}
void (*p[4]) (void);
int main(void)
{
int result;
int i, j, op;
p[0] = f1;
p[1] = f2;
p[2] = f3;
p[3] = f4;
for(auto i= 0; i<4; ++i)
{
(*p[i])();
}
return 0;
}

Is this code legal in ISO C++?

So I'm trying to implement function parameters which can be uninitialized. Here is the code which I have written. My question is if it's legal by the ISO C++ standard (version 14 if possible).
#include <iostream>
#include <typeinfo>
using namespace std;
template<typename type>
struct nzeroinittmpliteral
{
nzeroinittmpliteral() { }
nzeroinittmpliteral(type arg) { d = arg; }
//nzeroinittmpliteral(const nzeroinittmpliteral &) = delete;
operator type () & { return d; }
operator type () && { return d; }
type d;
} ;
void func(bool bIsPointerValid, nzeroinittmpliteral<int *> pVar = {})
{
if(bIsPointerValid)
{
cout << *pVar << endl;
}
else
{
pVar = new int;
*pVar = 8;
cout << *pVar << endl;
delete pVar;
}
}
int main()
{
func(true, { (int *)&(const int &)int{9} } );
func(false);
}
If you want to pass a parameter that may be uninitialized, simply don't pass it, use overloading. Look:
void func(int value)
{
cout << value << endl;
}
void func()
{
// no 'value' was initialized here :)
func(8);
}
Or simply give a default value to the parameter if you will provide one anyway in your body:
void func(int value = 8)
{
cout << value << endl;
}
Besides that, you can take a look at boost::optional:
void func(boost::optional<int> optvalue = boost::none) {
if (optvalue) {
cout << *optvalue << endl;
} else {
// nothing passed
cout << "foo" << endl;
}
}
Directly answering your question: your code is valid.
func(true, { (int *)&(const int &)int{9} } );
By casting the temporary to a const reference, you extend its lifetime to the lifetime of the reference itself, which ends after func returns. But this is too redundant, you could simply have written:
void func(int* value) { if (value) {...} }
func(&(const int &)9);
func(nullptr);
The actual parameter being passed is your nzeroinittmpliteral and it is initialized by calling one of the constructors, always. The default constructor doesn't initialize the d member, but this is no big improvement as it is just a pointer. Using nullptr is better and removes the need for the bool parameter.

Counting of objects created in stack and heap for many classes

What is the best way to count the total number of objects created in both stack and heap for different classes. I know that in C++ new and delete operators can be overloaded and hence in the default constructor and destructor the object count can be incremented or decremented as and when the objects get created or destroyed.
Further if i am to extend the same thing for object counting of objects of different classes, then i can create a dummy class and write the object count code in that class and then when i create any new class i can derive it from the Dummy class.
Is there any other optimal solution to the same problem.
then i can create a dummy class and write the object count code in that class and then when i create any new class i can derive it from the Dummy class.
Yes, but since each class needs its own count, you have to make a base class template and use the curiously recurring template pattern (CRTP):
template <class Derived>
class InstanceCounter
{
static int count;
protected:
InstanceCounter()
{
++count;
}
~InstanceCounter()
{
--count;
}
public:
static int instance_count()
{
return count;
}
};
template <class Derived>
int InstanceCounter<Derived>::count = 0;
class Test : public InstanceCounter<Test>
{
};
int main()
{
Test x;
std::cout << Test::instance_count() << std::endl;
{
Test y;
Test z;
std::cout << Test::instance_count() << std::endl;
}
std::cout << Test::instance_count() << std::endl;
}
The way the object is created in stack and heap is different.
The new operator is used create an object in heap, and normal object declaration will create an object in stack.
So by overloading an new operator we can count the object created in heap.
static variable can be used to count the objects.
To find the no of objects created on Heap and Stack. To create the object on the heap we use new so override the new and delete keywords to keep track of the counter.
class Test
{
static int heapcount;
static int stackcount;
public:
static int GetHeapCount()
{
return heapcount;
}
static int GetStackCount()
{
//The objects which are created on heap also will call constructor and increment the stack count, so remove the objects that are created on heap to get stack count
return stackcount - heapcount;
}
Test()
{
++stackcount;
}
~Test()
{
--stackcount;
}
void* operator new(size_t size)
{
++heapcount;
void * p = malloc(sizeof(Test));
return p;
}
void operator delete(void* p)
{
--heapcount;
free(p);
}
void operator=(Test const& obj)
{
int x = 0;
}
};
int Test::heapcount = 0;
int Test::stackcount = 0;
int main()
{
{
Test t;
Test t2;
Test* t1 = new Test();
std::cout << "HeapCount = " << Test::GetHeapCount() << std::endl;//HeapCount = 1 (t1)
std::cout << "StackCount = " << Test::GetStackCount() << std::endl;//StackCount = 2 (t,t2)
delete t1;
}
//As all the objects are deleted so count must be zero, stack objects will be removed when goes out of scope
std::cout << "HeapCount = " << Test::GetHeapCount() << std::endl;//HeapCount = 0
std::cout << "StackCount = " << Test::GetStackCount() << std::endl;//StackCount=0
{
Test t[3];
Test* t2 = new Test();
Test* t3 = new Test();
std::cout << "HeapCount = " << Test::GetHeapCount() << std::endl;//HeapCount = 2 (t2,t3)
std::cout << "StackCount = " << Test::GetStackCount() << std::endl;//StackCount = 3 (t[3])
}
//Two heap objects are not deleted, but stack objects has been cleaned
std::cout << "HeapCount = " << Test::GetHeapCount() << std::endl;//HeapCount = 2
std::cout << "StackCount = " << Test::GetStackCount() << std::endl;//StackCount = 0
}

initialize reference in initialization list

I was told the reference variable must be initialized in the initialization list, but why this is wrong?
class Foo
{
public:
Foo():x(0) {
y = 1;
}
private:
int& x;
int y;
};
Because 0 is a temporary object? If so, what kind of object can reference be bound? The object which can take an address?
Thanks!
0 is not an lvalue, it's an rvalue. You cannot modify it, but you're trying to bind to a reference where it could be modified.
If you make your reference const, it will work as expected. Consider this:
int& x = 0;
x = 1; // wtf :(
This obviously is a no-go. But const&'s can be bound to temporaries (rvalues):
const int& x = 0;
x = 1; // protected :) [won't compile]
Note that the life-time of the temporary is ended at the completion of the constructor. If you make static-storage for your constant, you'll be safe:
class Foo
{
public:
static const int Zero = 0;
Foo() : x(Zero) // Zero has storage
{
y = 1;
}
private:
const int& x;
int y;
};
Well, you can never change it, 0 can never equal anything other than 0.
try
class Foo
{
public:
Foo(int& a):x(a) {
y = 1;
}
private:
int& x;
int y;
};
Alternatively, you can do this if your reference is constant because then 0 can only ever equal zero
A long lived reference must be bound to an lvalue. Basically, as you so eloquently put it, an object that has a definite address. If they are bound to a temporary the temporary will be destroyed while the reference is still referencing it and the results are undefined.
Short lived const references (local function variables and function arguments) can be bound to temporaries. If they are, the temporary is guaranteed to not be destroyed until the reference goes out of scope.
Demonstration code:
#include <iostream>
class Big {
public:
Big() : living_(true), i_(5) { // This initialization of i is strictly legal but
void *me = this; // the result is undefined.
::std::cerr << "Big constructor called for " << me << "\n";
}
~Big() {
void *me = this;
living_ = false;
::std::cerr << "Big destructor called for " << me << "\n";
}
bool isLiving() const { return living_; }
const int &getIref() const;
const int *getIptr() const;
private:
::std::string s_;
bool living_;
const int &i_;
char stuff[50];
};
const int &Big::getIref() const
{
return i_;
}
const int *Big::getIptr() const
{
return &i_;
}
inline ::std::ostream &operator <<(::std::ostream &os, const Big &b)
{
const void *thisb = &b;
return os << "A " << (b.isLiving() ? "living" : "dead (you're lucky this didn't segfault or worse)")
<< " Big at " << thisb
<< " && b.getIref() == " << b.getIref()
<< " && *b.getIptr() == " << *b.getIptr();
}
class A {
public:
A() : big_(Big()) {}
const Big &getBig() const { return big_; }
private:
const Big &big_;
};
int main(int argc, char *argv[])
{
A a;
const Big &b = Big();
const int &i = 0;
::std::cerr << "a.getBig() == " << a.getBig() << "\n";
::std::cerr << "b == " << b << "\n";
::std::cerr << "i == " << i << "\n";
return 0;
}
And the output:
Big constructor called for 0x7fffebaae420
Big destructor called for 0x7fffebaae420
Big constructor called for 0x7fffebaae4a0
a.getBig() == A living Big at 0x7fffebaae420 && b.getIref() == -341121936 && *b.getIptr() == -341121936
b == A living Big at 0x7fffebaae4a0 && b.getIref() == 0 && *b.getIptr() == 0
i == 0
Big destructor called for 0x7fffebaae4a0