I'am a little bit confused about operator overloading new and delete.
I wrote some test :
#include <iostream>
using namespace std;
class Test
{
public :
Test()
{
cout << "Test - ctor" <<endl;
}
~Test()
{
cout << "Test - dtor" <<endl;
}
Test(const Test& t)
{
cout << "Test - copy ctor" <<endl;
}
Test& operator = (const Test& t)
{
cout << "Test - assiment operator" <<endl;
}
void* operator new(size_t size)
{
cout << "Test - operator new" <<endl;
return NULL;
}
void print()
{
cout << "print" << endl;
}
};
int main()
{
Test* t = new Test();
t->print();
return 0;
}
And the output is :
Test - operator new
Test - ctor
print
Now, if I return "NULL" from "new" , why my program doesn't crash when I call to print function?
thanks.
Because print() doesn't actually need anything of it's class Test. All it does is print a message to stdout. Remember that t->print(); is the same as print(t);, your function signature is actually:
void print(Test* t);
But that's all done by the compiler for you.
t just isn't used in the method and thus you're (un)lucky because it runs. This is still just plain undefined behaviour though.
If you absolutely want to see things crash and burn then change your class a bit:
class Test
{
public :
Test() : x(0)
{
cout << "Test - ctor" <<endl;
}
~Test()
{
cout << "Test - dtor" <<endl;
}
Test(const Test& t)
{
cout << "Test - copy ctor" <<endl;
}
Test& operator = (const Test& t)
{
cout << "Test - assiment operator" <<endl;
}
void* operator new(size_t size)
{
cout << "Test - operator new" <<endl;
return NULL;
}
void print()
{
cout << "print" << x << endl;
}
private:
int x;
};
This specific phenomenon has nothing to do with your operator new function.
The behaviour on calling a member function through a NULL pointer is undefined. Your result is a manifestation of that undefined behaviour.
It just happens to work in your particular case (possibly because your class is just a bag of functions).
(These days it's a good idea to use nullptr rather than the old-fashioned and not absolutely correct NULL.)
Related
I don't understand why a move constructor is being invoked during the main function in the code below, specifically the output is:
FString::FString(string one)
FString::FString(string two)
FString::Move Constructor
FString::Move Assign
COMPLETE
So the line I am concerned about is "FString::Move Constructor" - this implies to me that the move constructor is getting invoked in order to fulfill the return statement of the function GetStringTemp(), but from what I understood NRVO should mean that the move constructor should not be invoked. Am I misunderstanding the behaviour of NVRO? Thanks in advance
#include <iostream>
#include <string>
class FString
{
public:
FString(std::string newstring)
: _string(newstring)
{
std::cout << "FString::FString(string "+newstring+")" << std::endl;
}
FString(const FString& rhs)
{
std::cout << "FString::Copy Constructor" << std::endl;
}
FString(FString&& rhs)
{
std::cout << "FString::Move Constructor" << std::endl;
}
FString& operator=(const FString& rhs)
{
std::cout << "FString::Copy Assign" << std::endl;
return *this;
}
FString& operator=(FString&& rhs)
{
std::cout << "FString::Move Assign" << std::endl;
return *this;
}
void Print()
{
std::cout << "Printing: "+_string << std::endl;
}
private:
std::string _string;
};
FString GetTempString()
{
FString temp = FString("two"); // 2: Expected Constructor cout
return temp; // No expected constructor as NVRO assumed
}
int main()
{
FString myString = FString("one"); // 1: Expected Constructor cout
myString = GetTempString(); // 3: Expected Move Assignment cout
std::cout << "COMPLETE" << std::endl;
}
This question already has answers here:
What is a converting constructor in C++ ? What is it for?
(3 answers)
Closed 3 years ago.
I am confused how can we pass an integer when the parameter of a function only accept a class of type enemy ( void foo(const Enemy& inKlep ).
Yet when we pass to it an int (300) it compiles. Why is this?
#include <iostream>
using namespace std;
class Enemy {
public:
Enemy() { cout << "E ctor" << endl; }
Enemy(int i) { cout << "E ctor " << i << endl; }
Enemy(const Enemy& src) {cout << "E copy ctor"<< endl;}
Enemy& operator=(const Enemy& rhs) {cout<<"E="<<endl;}
virtual ~Enemy() { cout << "E dtor" << endl; }
void hornet(int i=7) const { // Not virtual!
cout << "E::hornet " << i << endl;
}
};
class Scott : public Enemy {
public:
Scott() : Enemy(1) { cout << "S ctor" << endl; }
Scott& operator=(const Scott& rhs) {cout<<"S="<<endl;}
virtual ~Scott() { cout << "S dtor" << endl; }
void hornet(int i=7) const {
cout<<"S::hornet " << i << endl;
}
};
void foo(const Enemy& inKlep) {
Enemy theEnemy;
inKlep.hornet(2);
}
int main(int argc, char** argv) {
foo(300);
cout << "Done!" << endl; // Don't forget me!
}
In C++, it is valid code for an input parameter to implicitly construct an object if the function expects an object that can be constructed from that parameter. So, for example:
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
func(5); //Valid; will print '5' to the console
}
If you don't want to allow this, you need to add the keyword explicit to the constructor to prevent this.
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
explicit CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
//func(5); //Invalid; will cause a compile-time error
func(CustomInt(5)); //Valid; will print '5' to the console
}
I was playing with overloading different operators and added print statements to watch what was happening. When I overloaded the post increment operator, I saw that the constructor was being called twice, but I don't understand why.
#include <iostream>
using namespace std;
class ParentClass {
public:
ParentClass() {
cout << "In ParentClass!" << endl;
}
};
class ChildClass : public ParentClass {
public:
int value;
ChildClass() { }
ChildClass(int a)
: value(a) {
cout << "In ChildClass!" << endl;
}
int getValue() { return value; }
ChildClass operator++( int ) {
cout << "DEBUG 30\n";
this->value++;
return this->value;
}
};
int main() {
cout << "DEBUG 10\n";
ChildClass child(0);
cout << "value initial = " << child.getValue() << endl;
cout << "DEBUG 20\n";
child++;
cout << "DEBUG 40\n";
cout << "value incremented = " << child.getValue() << endl;
}
The output after running this code is:
DEBUG 10
In ParentClass!
In ChildClass!
value initial = 0
DEBUG 20
DEBUG 30
In ParentClass!
In ChildClass!
DEBUG 40
value incremented = 1
This statement
return this->value;
Says return int
But the method prototype is
ChildClass operator++( int )
So the compiler thinks, got an int need a ChildClass - Lets construct one from the int. Hence the output
I have defined a normal class T:
class T {
public:
T() { cout << "default constructor " << this << "\n" }
T(const & T a) { cout <<"constructor by copy " << this << "\n"}
~T() { cout << "destructor "<< this << "\n"}
T & operator=(T & a) {
cout << " assignemnt operator :" << this << " = " << &a << endl;}
};
And there are 4 functions, one of which is wrong:
T f1(T a){ return a; }
T f2(T &a){ return a; }
T &f3(T a){ return a; }
T &f4(T &a){ return a; }
Does anyone know which one is wrong?
f3 is wrong, because it is returning a reference to a local object.
Parameters passed by value are copied. Their copies are local to functions to which they are passed - they go out of scope as soon as the function returns.
I have the following small class:
/// RAII wrapper for a Lua reference
class reference
{
public:
/// Construct empty reference
reference() : m_L(NULL), m_ref(LUA_NOREF) {}
/// Construct reference from Lua stack
reference(lua_State* L, int i = -1) : m_L(L) {
lua_pushvalue(L, i);
m_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
/// Destructor
~reference() {
if (m_L) luaL_unref(m_L, LUA_REGISTRYINDEX, m_ref);
}
/// Copy constructor
reference(const reference& r) : m_L(r.m_L) {
r.push();
m_ref = luaL_ref(m_L, LUA_REGISTRYINDEX);
}
/// Move constructor
reference(reference&& r) : m_L(r.m_L), m_ref(r.m_ref) {
r.m_L = NULL; // make sure r's destructor is NOP
}
/// Assignment operator
reference& operator=(reference r) {
swap(r, *this);
return *this;
}
/// Swap with other reference
friend void swap(reference& a, reference& b)
{
std::swap(a.m_L, b.m_L);
std::swap(a.m_ref, b.m_ref);
}
void push() const { lua_rawgeti(m_L, LUA_REGISTRYINDEX, m_ref); }
private:
lua_State* m_L;
int m_ref;
};
Note that the assignment operator is implemented using the copy-and-swap idiom and is supposed to call the move constructor, if used with an rvalue.
However, reference r; r = reference(L); calls the copy constructor before entering the assignment operator. Why, oh why?
Writing two assignment operators helps:
/// Assignment operator
reference& operator=(const reference& r) {
reference copy(r);
swap(copy, *this);
return *this;
}
/// Move assignment operator
reference& operator=(reference&& r) {
swap(r, *this);
return *this;
}
However, at the cost of disabling copy elision.
Isn't pass-by-value supposed to work here as expected? Or is even my compiler (Clang on Mac) broken?
Update:
The following small test-case works correctly:
#include <iostream>
using namespace std;
struct resource
{
resource(int i=1) : i(i) { print(); }
~resource() { print(); i = 0; }
void print() const
{
cout << hex << " " << uint16_t(uintptr_t(this)) << ") " << dec;
}
int i;
};
resource* alloc_res()
{
cout << " (alloc_res";
return new resource(0);
}
resource* copy_res(resource* r)
{
cout << " (copy_res";
return new resource(r->i);
}
void free_res(resource* r)
{
if (r) cout << " (free_res";
delete r;
}
struct Test
{
void print() const
{
cout << hex << " [&=" << uint16_t(uintptr_t(this))
<< ", r=" << uint16_t(uintptr_t(r)) << "] " << dec;
}
explicit Test(int j = 0) : r(j ? alloc_res() : NULL) {
cout << "constructor"; print();
cout << endl;
}
Test(Test&& t) : r(t.r) {
cout << "move"; print(); cout << "from"; t.print();
t.r = nullptr;
cout << endl;
}
Test(const Test& t) : r(t.r ? copy_res(t.r) : nullptr) {
cout << "copy"; print(); cout << "from"; t.print();
cout << endl;
}
Test& operator=(Test t) {
cout << "assignment"; print(); cout << "from"; t.print(); cout << " ";
swap(t);
return *this;
cout << endl;
}
void swap(Test& t)
{
cout << "swapping"; print();
cout << "and"; t.print();
std::swap(r, t.r);
cout << endl;
}
~Test()
{
cout << "destructor"; print();
free_res(r);
cout << endl;
}
resource* r;
};
int main()
{
Test t;
t = Test(5);
}
If compiled with clang++ --std=c++11 -O0 -fno-elide-constructors test.cpp -o test the move constructor is called. (Thanks for the switch, Benjamin Lindley)
The question is now: why does it work now? What's the difference?
There is no legal C++11 circumstance that would cause the calling of a copy constructor in r = reference(L);.
This is effectively equivalent to r.operator =(reference(L));. Since operator= takes its parameter by value, one of two things will happen.
The temporary will be used to construct the value. Since it's a temporary, it will preferentially call reference's move constructor, thus causing a move.
The temporary will be elided directly into the value argument. No copying or moving.
After this, operator= will be called, which doesn't do any copying internally.
So this looks like a compiler bug.