calling function whose name is class name itself? - c++

I do not know what methodology they use since the code base is huge.
It defined a class like this:
class ABC {
member_func(string c);
};
main() {
ABC("").member_func("this random string");
}
What is the missing code that would enable us to call ABC("");?
I did not see any object of that class created anywhere.

That simply constructs an object of type ABC, but doesn't initialize any permanent memory location with that object. I.e., the initialized object the call to the ABC constructor creates is a temporary, and is lost after the call since it is not constructed in a memory location that can be accessed after the call such as an automatic variable on the stack, a static memory location, etc. So the "missing" code to make a call like that usable in the "real-world" is to actual name an object that is constructed so that it can be accessed later... for example, something like ABC my_object(""); or ABC my_object = ABC("");.
UPDATE: In the updated code you've posted, what's taking place is again a temporary object of type ABC is being constructed, and then a non-static method of class ABC called member_func is being called on the temporary that was created by the call to ABC's constructor. Of course for this code to have any meaning in the "real world", that call to member_func would have to contain some side-effect that would be visible outside of the class instance (i.e., the class instance could be containing a data-member that is a pointer to some shared memory object that the call then modifies). Since though from the code sample you've posted there does not seem to be any side-effects from the call, it's for all intents and purposes a non-operation ... a temporary ABC class instance is created, it has a method called on the instance, and then any reference to the instance is lost since it was not constructed in a memory location accessible from the current scope of main().

class ABC
{
std::string d;
public:
ABC(std::string x) // For the ABC("").
{ d = x; }
void foo(std::string x) // For the foo("").
{ std::cout << d << std::endl << x << std::endl; }
};
int main()
{
ABC("This creates a temporary object.").foo("This calls foo().");
// Is the same as...
{
ABC obj("This creates another object.");
obj.foo("This calls obj.foo().");
} // obj is destroyed.
return(0);
}
Self explanatory... I hope. :)

Related

Overwrite stack-allocated instance of a class

Consider the following code:
class A{
public:
A(){};
};
int main(){
A a = A();
std::cout << &a << std::endl;
a = A();
std::cout << &a << std::endl;
return 0;
}
Both addresses are the same. The behavior that I expected was that the second call to A() would overwrite the variable a by creating a new instance of A, thereby changing the new address of a.
Why is this so? Is there a way to statically overwrite a that I am not aware of?
Thank you!
Why is this so?
Within the scope of its lifetime, a variable is exactly one complete object (except in the case of recursion in which case there are multiple overlapping instances of the variable). a here is the same object from its declaration until the return of the function.
I expected was that the second call to A() would overwrite the variable a by creating a new instance of A,
It did that.
thereby changing the new address of a.
It didn't do that. The temporary object created by A() had a new address, but that temporary object was destroyed at the end of that full expression. a remained where it had been, and you invoked its assignment operator with the temporary object as the argument.
The variable a is allocated on the stack. Its address is not going to change for the duration of the function. The first and the second instance of class A will be created in the space taken up but the variable.

When is rvalue destructor called / is this ok

Is the following wrapper class an "OK" way of keeping an intermediate object with std::unique_ptr to access the me member without copying me?
Here is the example
#include <iostream>
#include <memory>
/* myobj from another library */
class myobj {
public:
std::string me; /* actual member of interest is larger and more
complicated. Don't want to copy of me or myobj */
/* more members in actual class */
myobj(std::string i_am) {
/* more stuff happens in constructor */
me = i_am;
}
~myobj(){
std::cout << me << ": Goodbye" << std::endl;
}
};
/* A function in another library */
void who_is_this(std::string *who){
std::cout << "This is " << *who << std::endl;
}
/* wrapper which I define */
class myobj_wrapper {
using obj_ptr = std::unique_ptr<myobj>;
obj_ptr ptr;
public:
std::string *who;
myobj_wrapper(std::string i_am):
ptr(new myobj(i_am)), who(&ptr.get()->me) {}
myobj_wrapper(myobj &the_obj): who(&the_obj.me) { }
};
int main()
{
{
myobj bob("Bob");
who_is_this(myobj_wrapper(bob).who);
}
who_is_this(myobj_wrapper("Alice").who);
return 0;
}
The resulting program yields
This is Bob
Bob: Goodbye
This is Alice
Alice: Goodbye
I define myobj_wrapper for multiple object to get the who pointer. What I am unsure of whether the object of interest (std::string in the above) will get destroyed before it is evaluated in the who_is_this function. It does not seem to from the above but should I expect this? Are there pitfalls with the above solution?
I am not sure, but here is my point of view:
who_is_this(myobj_wrapper("Alice").who);
This will create a wrapper object, that will take the string literal as its argument. Then, a myobj instance will be dynamically created, and handed over to a unique pointer. Via that instance, we get its data (the string), and make a traditional pointer from the wrapper class point to it. So, now who is pointing to me, i.e. Alice.
We pass who (which is a pointer) to:
void who_is_this(std::string *who)
which means that the function's parameter who is not a copy, but points to the original data.
So now the whole question is when the wrapper object will go out of scope (thus its data member (the unique pointer) will go out of scope too, meaning that the myobj instance which had been dynamically created will be garbage collected, which in turns means that me will go out of scope too, and so will who.
The wrapper object will go out of scope, after who_is_this() gets executed, which means that your code is OK.

When creating a second object in C++ through the first object, where does the first object go?

I am currently reading the second edition of C++: A Beginner's Guide by Herbert Schildt.
In Module 9.4, he talks about returning objects:
Just as objects can be passed to functions, functions can return objects. To return an object, first declare
the function as returning a class type. Second, return an object of that type using the normal return
statement. The following program has a member function called mkBigger( ). It returns an object that
gives val a value twice as large as the invoking object.
This is the 'following program' he mentions:
// Returning objects.
#include <iostream>
using namespace std;
class MyClass {
int val;
public:
// Normal Constructor.
MyClass(int i) {
val = i;
cout << "Inside constructor\n";
}
~MyClass() {
cout << "Destructing\n";
}
int getval() { return val; }
// Return an object.
MyClass mkBigger() {
Myclass o(val * 2); // mkBigger() returns a MyClass object.
return o;
}
};
void display(MyClass ob)
{
cout << ob.getval() << '\n';
}
int main()
{
cout << " Before Constructing a.\n";
MyClass a;
cout << "After constructing a.\n\n";
cout << "Before call to display.\n";
display(a);
cout << "After display() returns.\n\n";
cout << "Before call to mkBigger().\n";
a = a.mkBigger();
cout << "After mkBigger() returns.\n\n";
cout << "Before second call to display.\n";
display(a);
cout << "After display() returns.\n\n";
return 0;
}
This gives us the following output:
Before Constructing a.
Inside constructor
After constructing a.
Before call to display.
10
Destructing
After display() returns.
Before call to mkBigger()
Inside constructor
Destructing
Destructing
After mkBigger() returns.
Before second call to display.
20
Destructing
After display() returns.
Destructing
Schildt then goes on to explain that the reason there are two 'Destructing' messages during the mkBigger() call is because of the fact that:
when an object is returned by a function, a temporary object is automatically created, which holds the return value. It is this object that is actually returned by the function. After the value has been returned, this object is destroyed.
I was actually surprised there wasn't 3 'Destructing' messages. I have the following issue: Given the definition of mkBigger(), a new MyClass instance is created, and it is that instance that is returned and placed in the address of a. Thus, when doing
a = a.mkBigger();
My impression is thus that the original object previously held in a is no longer referenced by a. Is this correct? If so, I then have the following issues:
I was told C++ has some minute notions of garbage collection. Would that object thus be garbage-collected? where is this object now? Is this an example of the possible feared memory leaks that many mention when talking about the 'dangers' of C++?
One of the destructor in mkbigger() is called on o, the MyClass instance passed in by value; it goes out of scope at the end of the function. The other is called on the temporary copy of o returned when it is destroyed. What else goes out of scope? Not a in main(); therefore you should not expect a third destructor to be called. C++ does not provide garbage collection outside of calling destructors when automatic objects go out of scope.
Unlike some other modern languages, a does not "hold a reference" to an object; a is the object, in that it is a certain number of bytes holding the raw data members. When you do a = a.mkBigger();, MyClass's default assignment operator is called, which simply copies the val inside the temporary object on the right hand side into the val inside a, overwriting the value that was already there. a = a.makeBigger() would be equivalent to a.val = a.makeBigger().val if val were public.
Memory leaks occur when you use new to allocate memory and then fail to use delete to deallocate that memory. For classes that do this internally, you must write at least your own copy constructor, assignment operator, and destructor.

explanation of c++ class instances behavor

I Can't properly understand what is exactly happening when class instances are creating and when an instances methods are invoking.
For example there's a folowing c++ code:
class A {
int a;
void print_my_a();
public:
A();
};
void A:: print_my_a() {
cout << a << '\n';
}
A::A(): a(10) {}
int main() {
A Aobj1 = A();
A Aobj2 = A();
Aobj1.print_my_a();
Aobj2.print_my_a();
return 0;
}
so the question is:
Do each Aobj1 and Aobj2 instance refer to only one print_my_a() method ? or they both have their own print_my_a()?
All functions are code, and all code in C++ is shared. However, it does not really make any difference, because the code cannot be modified anyway.
However, the local variables created during the runtime of each method, instance or static, are per invocation, so if you call the same method twice, concurrently or not, each method would have its own local variables.
What you see is only an abstraction over the layout of data and code in the executable. Functions have one copy in the code segment and are shared between objects.
The code for the method exists only once, but "this"-pointer "passed" to the method will be different.
If you rewrite print_my_a as follows, it gets much clearer:
void A::print_my_a() {
cout << this->a << '\n';
}
Hence:
Aobj1.print_my_a() will have this pointer pointing to Aobj1
and Aobj2.print_my_a() will have this pointer pointing to Aobj2.
An object owns it's own instance of data members. So a separate instance of int a is owned by both of your objects Aobj1 & Aobj2. The methods are not owned by the object, but they use the state of the object (the data member instances for the object) which has made the call.

C++ class instantiation theory

#include <iostream>
using namespace std;
class A {
public:
A() {
cout << "Default Ctor" << endl;
}
};
int main() {
A(); // <------- Problem
return 0;
}
It shows Default Ctor on console. My questions
Is is valid?
If so, how did it instantiate since I didn't use new or any object?
You are creating a new object with A().
Is is valid?
Yes it is.
If so, how did it instantiate since I didn't use new or any object?
new simply creates the object in dynamic memory. You're creating the object in automatic memory. Also, just because you didn't give the object a name, doesn't mean it isn't created.
Think of this:
int foo() { return 1; }
int main()
{
foo();
}
Leaving optimizations aside Did foo() actually return 1? Yes it did. Just that you're not using it.
EDIT:
Let's break it down a bit:
A(); //creates a temporary unnamed object in automatic storage
A a; //creates an object a of type A in automatic storage
A a(); //creates no object, but declare a function a returning A and taking no parameters
A a(A()); //these two are equivalent
A a = A(); //creates a temporary unnamed object and creates an object a in automatic storage
//using the compiler-generated copy constructor
A a;
a = A(); //creates an object a in automatic storage
//creates an unnamed temporary object and uses the compiler-generated assignment operator
//to assign it to a
A a = &A(); //invalid, &A() is the address of a temporary a, which is illegal
Is is valid?
Yes, It is valid
What exactly happens?
A();
Creates a temporary nameless object of the type A by calling its default no argument constructor but the object is destructed by the time the next statement is executed since.
If so, how did it instantiate since I didn't use new or any object?
You can create objects on the local/automatic storage or on dynamic storage depending on your usage.
When you use new objects are created on dynamic storage(heap), when you create a object as you have it is created on the local/automatic storage(stack).
So using new only determines where the object will be created not whether it will be created.
What are Temporary Nameless objects?
You do not always need to name an object to instantiate them.
For Ex:
While calling function, when you pass objects by value temporary nameless objects are created and automatically destroyed all the time.These are objects which do not have any name and hence cannot be explicitly referred through program but they do serve the purpose for which they were created.
In simple words,
You are creating a nameless temporary object on the local/automatic storage which does not exist once the statement completes execution.