C++11 for STAR.comments
P { margin-bottom: 0.08in; }CODE.cjk { font-family: "AR PL UMing HK",monospace; }CODE.ctl { font-family: "Lohit Devanagari",monospace; }A:link { }
PRE.cjk { font-family: "AR PL UMing HK",monospace; }PRE.ctl { font-family: "Lohit Devanagari",monospace; }H3 { margin-bottom: 0.08in; }H3.cjk { font-family: "AR PL UMing HK"; }H3.ctl { font-family: "Lohit Devanagari"; }P { margin-bottom: 0.08in; }CODE.cjk { font-family: "AR PL UMing HK",monospace; }CODE.ctl { font-family: "Lohit Devanagari",monospace; }A:link { }
>---------------------------------------------------------------------------------------------------------------------------
> As a general rule, put function definitions into the .cxx
file and let the compiler decide what gets
> inlined (it can decide anyway, regardless of the inline keyword).
Generally I agree. But you mentioned “ let the compiler decide” which is not clear.
If user used package A and
in A.h int foo();
in A.cxx int foo(){return 0;}
Then user calls foo()
How compiler could do inline if it does not know where is the definition of foo()
Especially in the case where package A in library.
Additionally , when function is defined in .h file, gdb usually can not see it and can not set break.
So for debugging to put function into .cxx is good.
>---------------------------------------------------------------------------------------------------------------------------
>Decision: Avoid the use ROOT definitions of built-in data types and use the built-in C++ types
> Use int
instead Int_t
, float
instead of Float_t
, double
instead of Double_t
, etc.
Double32_t Double 8 bytes in memory, written as a 4 bytes float
Float16_t Float 4 bytes written with a truncated mantissa
>---------------------------------------------------------------------------------------------------------------------------
> Avoid using smart pointers in STAR code.
I agree with it. But inSTAR code a lot of classes have no relation to ROOT.
For these ones, probably smart pointers could be allowed.
>---------------------------------------------------------------------------------------------------------------------------
> When the logic of a program guarantees that a given instance of a base class is in fact an instance
> of a particular derived class, then use of a dynamic_cast
or static_cast
as an alternative
> may be also justified in such situations.
Note: Using dynamic_cast
with classes without virtual function is senseless. It is impossible
recognize type of class in this case and dynamic_cast
==> static_cast
>---------------------------------------------------------------------------------------------------------------------------
> Prefer the prefix form of the increment (++i) and decrement (--i)
> operators because it has simpler semantics.
But user should remember that lines:
a = ++i;
and:
a = i++;
give different value of a.
>---------------------------------------------------------------------------------------------------------------------------
> Loops and Switch Statements.
> default: {
> assert(false);
Agree. It was discussion to use assert() here or not.
Wrong case means that code is completely wrong.
We can use return with error condition. Why it is not good.
1. Using error flag is not easy to implement if it is deep in code
2. Using exceptions also not good(see exceptions);
3. If we succeed to reach maker and then return StErr, most of
makers have no right to stop production. Then after many CPU days
we will produce wrong data, which we need to reprocess. Even that
will happen if somebody will look in the log file.
4. In the case of assert to find the bug is much easier.
========================================================================
OLD PART
========================================================================
> Each header file should contain only one or related class declarations for maintainability and for
> easier retrieval of class definitions.
It is not always good. Classes which are closely related with each other, are better to place together.
Like class of track parameters and class of parameter errors. Huge amount of small different files
is not manageable.
> Static variables in functions (called "function-local static variables" in the C++ terminology) are
> expensive and need care on destruction. Prefer to use static class variables where possible.
How they could be “expensive”? There is a lot of cases when they are convenient.
1. static int nCall = 0; nCall++; //counting the number of calls
2. static const double kQQQ = fun1(123.)*fun2(11.11)*sin(P_PI/3); // this constant calculated only once
3. the same especially important with arrays which must be calculated only once
4. static KONST* myk = KONST::instantiate(); // You can use once calculated pointer
But I agree, that using static variables for calculation is a bad idea. Especially if we will decide to use
threads.
> When using inheritance, make it public
and declare overridden methods as override
or final
.
I think that using “final” for STAR is not too good. In any physical experiment, software is changing
all the time. To decide that class or method is final is not realistic.
> Use multiple inheritance implementation only when at most one of the base classes has an
> implementation; all other base classes must be pure interface classes.
Even more, it is better to avoid multiple inheritance at all.
> If a class was designed as a pure interface, keep it as a pure interface.
Not clear at all.
“If a class was designed as a pure interface, keep it as a pure interface”
“If a class was NOT designed as a pure interface, keep it as NOT a pure interface”????
> Hide internals. Avoid returning handles to internal data managed by your class.
It is true, with exception of pointer to to evident array.
For instance:
double xyz[3];
xyz[0] = A.x()
xyz[1] = A.x()
xyz[2] = A.x()
is not too convenient. Better is:
const double *XYZ = A.X();
> Prefer the use of fundamental types built-in C++ over ROOT types, except where
> absolutely required.
True, ROOT types like Double_t should be used only for persistent data members, to avoid problems with I/O between different machines
>Use C++ exceptions instead of return codes for error handling. Do not use exceptions to return values.
>Exceptions should be used for error handling
In C++ lectures, lecturer told to avoid exceptions as much as possible. Especially for error handling.
When exception is occurred stack is decreased and some destructors are called. During that, especially
during error handling, some other exceptions happened. As a result all the memory is destroyed and
extremely hard to find the bug.
> Avoid magic numbers (hard coded numbers).
True, but there are exceptions of this rule. For instance:
double xyz[3]; // where 3 is 3 dimensional space.
Case with:
enum {N=3}
double xyz[N];
gives the wrong impression that N could be non 3
> Prefer small and focused functions.
Yes and No. If you have 300 small functions which are called each others, then code is unreadable and slow.
> In general, avoid designs that require casting. You may use static_cast
when necessary, but
> avoid const_cast
and reinterpret_cast
. C-casts are forbidden.
C-cast has the same behavior as static_cast
but expression:
(int*)p;
is less ugly and shorter than :
static_cast<int*>(p)
- perev's blog
- Login or register to post comments