Does C++ compiler automatically sets my function as static? - c++

Here's my question with sample code.
In the case a class function never uses instance related data or never references this, could the compiler decide this function is kind of static ?
As an example see this code (with description below) :
class Dummy
{
public:
Dummy()
{
std::cout << "Dummy()" << std::endl;
mInstance = this;
}
~Dummy()
{
std::cout << "~Dummy()" << std::endl;
mInstance = nullptr;
}
static Dummy& instance()
{
std::cout << "static Dummy& instance()" << std::endl;
return *mInstance;
}
void foo()
{
std::cout << "bar" << std::endl;
}
private:
int mData;
static Dummy* mInstance;
};
Dummy* Dummy::mInstance = nullptr;
At construction, my Dummy class references it's instance in a static variable called mInstance using a pointer.
mInstance is available through the static function instance().
foo() is not a static function. Hence I need and instance to call it.
mInstance is initialized to nullptr.
That case if my main only does :
Dummy::instance().foo();
I should get a seg fault. Because instance() would de-reference a nullptr.
Instead the program runs and the output will be :
bar
...And only this line so it does not seem to call neither the constructor nor the destructor.
Yet if my foo() function is :
void foo()
{
mData = 5;
std::cout << "bar" << std::endl;
}
Here a seg fault occurs.
I tend to guess as foo() actually did not reference anything proper to the instance, the compiler guessed it was a static and compiled this way.
But it does not seem to be logical as instance() function returns a reference to an instance and even if the foo() is static, foo() should not be callable...
As an other example, without the mData = 5 instruction, if my main is :
Dummy& vDummy = Dummy::instance();
std::cout << &vDummy << std::endl;
vDummy.foo();
The output is :
statci Dummy& instance()
0
bar
I don't really understand the way things are done here.... :/

You can think of member functions (non static) as functions with a hidden parameter that is a pointer to your object. So your void foo() could be considered as void foo(Dummy* d). And since you never use that pointer to Dummy, it does not matter if you pass a NULL pointer to it.
Hope this makes sense :)
For further reading about this type of undefined behaviour:
When does invoking a member function on a null instance result in undefined behavior?

The reason for this behaviour is that 'foo()' isn't virtual, so the object it's being called on is only used for type information at compile time. At runtime the fact that it's null has no effect, unless you used 'this' inside 'foo()', when you would get a nasty surprise, as you did when you tried to set a member variable, which uses 'this' implicitly.

Related

Implementation of a singleton class with atomic members

I'm trying to implement a class to track the performances of a multithreaded code and am running into the following issue.
The tracker should have a single instance, thus the singleton pattern.
In order to count object creation and function execution accross all the threads, I thought that using atomic member would be a good idea. But I can't seem to figure out a correct implementation.
This is a minimal code of what I wand to do:
#include <atomic>
#include <iostream>
class Counter
{
public:
static Counter& instance()
{
return instance_;
};
void increment()
{
counter_++;
};
private:
Counter ()
{
std::cout << "ctor counter" << std::endl;
};
~Counter ()
{
std::cout << "counter_: " << counter_ << std::endl;
std::cout << "dtor counter" << std::endl;
}
static Counter instance_;
std::atomic<int> counter_{0};
//int counter_ = 0;
};
Counter Counter::instance_ = Counter();
int main(void)
{
Counter::instance().increment();
Counter::instance().increment();
Counter::instance().increment();
return 0;
}
If the counter_ variable is an int, it works fine, but would not be thread safe.
If it is an atomic<int>, then the compiler tells me this:
g++ foo.cc
foo.cc:34:38: error: use of deleted function 'Counter::Counter(const Counter&)'
Counter Counter::instance_ = Counter();
^
foo.cc:4:7: note: 'Counter::Counter(const Counter&)' is implicitly deleted because the default definition would be ill-formed:
class Counter
^~~~~~~
foo.cc:4:7: error: use of deleted function 'std::atomic<int>::atomic(const std::atomic<int>&)'
In file included from foo.cc:1:0:
/usr/include/c++/7/atomic:668:7: note: declared here
atomic(const atomic&) = delete;
^~~~~~
I'm not sure I quite understand the problem. Any explanation/solution would be much appreciated.
Cheers
You could simplify by having std::atomic<int> counter_{0}; simply be a static class member instead of part of each instance. (Since you're ensuring that there's only one instance the class.)
Or if you're only using your "singleton" that way returning a reference to a static object, just make all of its members static so you don't need to even get a pointer to that single instance of it in the first place. Then it can just be a glorified namespace{} with public and private static member functions. I think the only point of a "singleton" is to delay initializing it until after static initialization by using a function-scoped static with a non-constant initializer, but you're not doing that.
The actual problem is in the copy-constructor of your class, which your static initializer uses the way you've written it. It constructs a temporary Counter(); and then copies it to static instance_ variable.
You can compile as C++17 where eliding of that copy is guaranteed (works on Godbolt with g++ -std=gnu++17 with your source untouched), or you can rewrite the initializer
Counter Counter::instance_; // default construct
Counter Counter::instance_{}; // explicitly default construct
Both of those work with g++ -std=gnu++11

undefined vs. deleted vs. undeclared function

I am using the default constructor as an example here, but the same question applies to all the special member functions.
Also, I am using https://en.cppreference.com instead of the standard because that is what I am reading and that is what I am having trouble understanding. If using the standard would change the question in any way, please let me know.
As stated in https://en.cppreference.com/w/cpp/language/default_constructor, if a class has no constructor then the compiler will always declare a default one. Then, if certain conditions aren't met, it will be undefined (pre c++11) or defined as deleted (post c++11).
All this seems to imply that there is a difference between a function being not declared, declared but not defined, or declared and deleted. However, all three options won't compile/link, e.g.
class MyClass {
public:
void foo();
void bar() = delete;
};
int main() {
MyClass c;
//c.foo(); // won't link
//c.bar(); // won't compile
//c.baz(); // won't compile
}
So why is it so important to change the definition from "declared and undefined" to "declared and deleted", and why not just leave it as "undeclared" in the first place?
So why is it so important to change the definition from "declared and undefined" to "declared and deleted"
Because of the difference: "won't link" vs "won't compile". This is a fundamental reason for why = delete was introduced: To catch the bugs of using (previously) undefined functions at compile time, rather than later. Furthermore, it allows better error diagnostic, since the compiler will be able to describe why the function is deleted. The best that the linker can say is that nobody defined it for some unknown reason.
There's no reason not to take advantage of the feature with the implicitly generated member functions.
The = deleted; declaration can be useful in various situations. As well as the very good reason given by eerorika, it can also be used to explicitly declare that a given 'special' function, such as the default constructor doesn't exist, and cannot be called.
It can also be used to specify that a function which exists in a base class does not exist in a derived class (which, by default, it will).
Here's a short piece of code showing such usage:
#include <iostream>
class foo {
private:
int m;
public:
foo() = delete; // Other programmers reading this definition will know immediately!
foo(int n) : m{ n } {} // ... that default ctor is intended not to be used
void inc() { ++m; } // ... rather than it has been omitted accidentally
int get() { return m; }
};
class bar : public foo {
public:
bar() : foo(0) {}
void inc() = delete; // Without this, code like `bar b; b.inc();` will call foo.inc()
};
int main() {
// foo f1; // error C2280: 'foo::foo(void)': attempting to reference a deleted function
foo f2(3); std::cout << f2.get() << std::endl;
f2.inc(); std::cout << f2.get() << std::endl;
bar b1; std::cout << b1.get() << std::endl;
// b1.inc(); error C2280: 'void bar::inc(void)': attempting to reference a deleted function
return 0;
}

Why does clang create these implicit methods when a class contains a virtual method?

I'm working on a tool based on clang's AST, and I'm curious to know why clang works this way.
Here's my input. I have a very simple class that is defined like this:
class Foo {
int foo();
};
Then in my RecursiveASTVisitor, I have code that looks like this:
bool MyASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl *D) {
for (auto const & method : D->methods()) {
llvm::outs() << method->getQualifiedNameAsString() << "(";
for (auto const & param : method->params())
llvm::outs() << param->getType().getAsString() << ", ";
llvm::outs() << ")";
if (method->isImplicit())
llvm::outs() << " [implicit]";
llvm::outs() << "\n";
}
return true;
}
All this does is spit out the list of methods defined in all the classes that are visited. The output for this is as we'd expect:
Foo::foo()
Now, let's make a small change to our Foo class. Let's make the foo() method virtual:
class Foo {
virtual int foo();
};
Now my output changes:
Foo::foo()
Foo::operator=(const class Foo &, ) [implicit]
Foo::~Foo() [implicit]
My question is, why does adding a virtual method to a class cause clang to create an implicit assignment operator and destructor? If I add --std=c++11, it creates an implicit move-assignment operator as well. Is this an implementation detail of clang, or is it part of the C++ standard?
Turns out that I should just read the clang source code. SemaDeclCXX.cpp has a method called Sema::AddImplicitlyDeclaredMembersToClass. There's a comment about why it declares the implicit copy assignment:
if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
++ASTContext::NumImplicitCopyAssignmentOperators;
// If we have a dynamic class, then the copy assignment operator may be
// virtual, so we have to declare it immediately. This ensures that, e.g.,
// it shows up in the right place in the vtable and that we diagnose
// problems with the implicit exception specification.
if (ClassDecl->isDynamicClass() ||
ClassDecl->needsOverloadResolutionForCopyAssignment())
DeclareImplicitCopyAssignment(ClassDecl);
}
So it does this in order to ensure that the implicitly defined methods, that may be virtual, end up in the right place in the vtable.

c++ global function vs data member function according to memory

Let's assume there is a kind of a function, which could be both global function or could be implemented as class member const function (not static, static means global). It depends on user's choice if the function will be called or not called at all. Let say - It is usually not called or called rare - in very special cases.
I am not interested of the program's logic organization. My question is about the memory usage. I know that data member function costs a little bit more (one pointer more), since it is called trough an object. What about the case if the function is not called in runtime?
If it is global function it will be resident in memory during program's lifelong no matter it is called or not. What about the case of data member function, since it is called through and object that is dynamically created, respectively - not created at all, what about the memory needed for the function, where it will be placed and what happens if an object is not created at all?
Thanks.
As was mentioned in the comments, a class member function in C++ can be thought of as a normal C-style function which implicitly takes as an argument a pointer to the instance of the class from which it is called. For example, consider the following C++ code:
class foo {
public:
void set(int j);
private:
int i;
};
void foo::set(int j) {
i = j;
}
The function foo::set can be thought of a C-style function which takes a (hidden) argument of type class foo *, and when you do foo a; a->set(3);, the class foo * that is (implicitly) passed is &a.
In summary, whether or not you ever call foo::set, it will be loaded into memory. (The only possible exception is if there are no calls to the function in your code at all, in which case an optimizer may remove it during compilation, but if it is possible to call it dynamically based on user input then it will be loaded.) On the other hand, no matter how many instances of class foo you have, only one copy of foo::set ever needs to exist in memory.
If your function isn't virtual then there is no overhead of being a member function (aka method).
In fact, in generated object code there is no such notion of a "member function" (unless it's virtual, more on that later). All methods are functions with special variable this. Compiler at the compile time knows what method is to be called at the run time, so it can generate method-specific object code (with some handling of this). By the way, that's the case why the following code doesn't crash:
#include <iostream>
class Crashy {
public:
void wouldItCrash() {
std::cout << "Hey, I'm still alive!" << std::endl;
}
};
int main() {
Crashy* ptr = 0;
ptr->wouldItCrash();
return 0;
}
Despite of null pointer there, programs successively finishes and prints "Hey, I'm still alive!". And that's okay if you think about method wouldItCrash as some kind of a function with special parameter this:
#include <iostream>
void Crashy__wouldItCrash(Crashy *this) {
std::cout << "Hey, I'm still alive!" << std::endl;
}
int main() {
Crashy* ptr = 0;
Crashy__wouldItCrash(ptr);
return 0;
}
We don't dereference the pointer in function, so no problems happen.
Consider the following simple program:
#include <iostream>
void FunctionName__() {
std::cout << "Hello from function!" << std::endl;
}
class ClassName__ {
public:
void MethodName1__() {
std::cout << "Hello from method 1!" << std::endl;
}
void MethodName2__() {
std::cout << "Hello from method 2!" << std::endl;
}
};
int main() {
FunctionName__();
ClassName__ a;
a.MethodName1__();
a.MethodName2__();
return 0;
}
If you compile it without optimizations (just g++ main.cpp) and then look at the symbols table (nm a.out), you'll see
0804876d T _Z14FunctionName__v
...
0804882c W _ZN11ClassName__13MethodName1__Ev
08048858 W _ZN11ClassName__13MethodName2__Ev
That is, all methods became just plain functions with special names (so no conflict could happen, see name mangling)
Virtual functions
As I said earlier, there are some special rules applying to the virtual functions. Virtual functions cannot be resolved at the compile-time (compiler doesn't know which instance of derived class will be processed at the run-time), so it's delayed to the run-time. So in order to serve virtual functions, each class (with that kind of functions, of course) has a special lookup table named virtual method table (aka vtable). In that case you clearly pay some memory space: you need a pointer to the function in the vtable and a pointer to the vtable for each instance of your class.
In typical C++ implementations:
A function is a function, regardless of whether it's a member function of some class, and it will reside in memory "forever" (disregarding demand-paging and all that).
A non-virtual member function is nothing more than an ordinary function that takes a hidden argument called this.
A virtual member function is a member function that has its address recorded in a dispatch table for the class that it belongs to.
So member functions are very much like ordinary functions, the main thing that changes is the way the call is done: with an additional argument, and possibly through a hidden function pointer.

Why does delete only work in main and not in a function that gets as an input the object or objects to be deleted?

I am trying to create two classes whose instances get created and deleted together. One class is a base for the other:
class Interface;
class MyClass
{
friend class Interface;
private:
MyClass() {}
public:
static MyClass *NewInstance();
Interface *ControlPanel;
};
class Interface : public MyClass
{
friend class MyClass;
private:
Interface() {}
public:
void Control1() {cout << "control1" << endl;}
void Control2() {cout << "control2" << endl;}
void Control3() {cout << "control3" << endl;}
};
The two member functions that are supposed to create and delete instances are:
MyClass *MyClass::NewInstance()
{
MyClass *inst = new MyClass;
inst->ControlPanel = new Interface;
return inst;
}
void DeleteMyClassInstance(MyClass *inst)
{
delete inst->ControlPanel;
inst->ControlPanel = 0;
delete inst;
inst = 0;
}
I had success in linking the instance creation process with the use of a function in the base class (NewInstance()) which creates the instances. But the deletion function (DeleteMyClassInstance()) doesn't work (that is, I can still use both inst1 and inst1->ControlPanel after calling the function):
int main()
{
MyClass *inst1 = MyClass::NewInstance();
inst1->ControlPanel->Control1();
DeleteMyClassInstance(inst1);
inst1->ControlPanel->Control1();
return 0;
}
But if I put the deletion code inside the main function, it works perfectly (the inst1->ControlPanel->Control1() statement that comes after the delete statements doesn't work, and that's what I want):
int main()
{
MyClass *inst1 = MyClass::NewInstance();
inst1->ControlPanel->Control1();
delete inst->ControlPanel;
inst->ControlPanel = 0;
delete inst;
inst = 0;
inst1->ControlPanel->Control1();
return 0;
}
My question is: Why does putting the delete statements directly inside the main function work while putting them inside a separate function and using it in main doesn't? Why does the code in my DeleteMyClassInstance() function get ignored by the compiler?
The main difference is that with the code in the main function inst=0 sets the variable in the main function to null. With the code in DeleteMyInstance, the line inst=0 only sets the local variable in DeleteMyInstance to null (uselessly, since it is unused after that point -- enable more warnings and your compiler might mention it). It doesn't affect the completely separate variable of the same name in main.
So, your code
DeleteMyClassInstance(inst1);
inst1->ControlPanel->Control1();
has undefined behavior because you attempt to use an object that has already been deleted. UB means that anything can happen. If it appears to work that is probably because in your implementation the function Control1 still "works" even when called on a null (or otherwise-invalid) pointer, since the function doesn't use this or any data members. But that implementation detail should not be relied on.
Be aware (if you aren't already) that your code shows some bad C++ style. You should not write special functions to delete objects owned by your class, that's what destructors are for. And you shouldn't have to explicitly delete objects in destructors, that's what smart pointers are for. And you shouldn't use dynamic allocation when not needed, that's what automatic variables and data members are for. By all means get this code right once, as a learning exercise what goes on behind the scenes, but that should be with a view to doing it properly as soon as possible.
Change your DeleteMyClassInstance function to.
void DeleteMyClassInstance(MyClass **inst)
{
delete (*inst)->ControlPanel;
(*inst)->ControlPanel = 0;
delete (*inst);
*inst = 0;
}