MISC about c++ core
class Transaction {
public:
// Equal if both the volume and price are equal
bool operator==(const Transaction& t) const
{
return (d_volume == t.d_volume)
&& (d_price == t.d_price);
}
bool operator!=(const Transaction& t) const
{
return !(*this == t);
}
};
class Transaction {
...
bool operator==(const Transaction& rhs) const;
};
Or
bool operator==(const Transaction& lhs,
const Transaction& rhs);
It's best that we also overload != when we overload ==.
T a(12)
: constructorT b = 12
is equivalent to: T tmp(12); b = temp; temp ~T;
explicit
class X {
public:
X(A); // Conversion from A to X
X(const B&); // Conversion from B to X
explicit X(C); // No implicit conversion
// from C to X
operator D() const; // Conversion from X to D, a bit dangerous
D toD() const; // this may be a better way to write conversion
...
};
int * p;
p = (int*) 123;
C++ has four cast operators:
static_cast<type>(expression)
const_cast<type>(expression)
dynamic_cast<type>(expression)
reinterpret_cast<type>(expression)
Cast is very powerful but is very dangerous, which can be legal but cause run-time errors.
class T {
public:
T(const T& rhs);
}
BSLS_ASSERT_SAFE(condition)
Condition is expensive to evaluate, greater big O than the function itselfBSLS_ASSERT(condition)
Condition is inexpensive to evaluate; default assert to useBSLS_ASSERT_OPT(condition)
Negligible cost of evaluation and great risk if ignoredbsls_Assert::setFailureHandler(&bsls_Assert::failThrow);
Install an alternate assertion-failure handler function
Assertion can be shut off in production by modifying the .mk file.
Can be overridden by an optional assertion-level flag Define the flag (macro) using the -D option,
Assertion must have no side effect!
In C++ 11, we have "static_assert", that does assertion in compile time. e.g.
static_assert(sizeof(int) == 4)
void foo(int arr[]); // … or …:
void foo(int *arr);
void foo(int arr[10])
because compiler doesn't check size, it is dangerous.void foo(int arr[], size_t size);
new
signal fails:while (true) {
// leak memory until we die...
try {
int *ip = new int(211);
} catch (const bsl::bad_alloc& e) {
bsl::cerr << "I'm exhausted!"
<< e.what() << "\n";
break;
}
}
foo(const )
In C++, defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.
In f()+g()
it is possible that either f() or g() will be executed first.
So be very careful when you write one expression thet contains multiple function whose behaviors are dependent with each other.
Another example:
cout << stack.pop() << stack.pop()
The interpreter may evaluate the second one first. It's called ambiguity.
Another famous example is i = i++
.
&&
, ||
. The expressin on the left will be executed before right.?
.void*
is not “a pointer to nothing” but rather “a pointer to anything”. It is a type supported in C and C++ to hold the value of any
pointer, regardless of target type. Any address can be stored in a void*
, however, they cannot be
dereferenced unless first cast into the correct pointer type.int i = 10;
void *pi = &i;
*pi = 5; // ERROR
*static_cast<int*>(pi) = 5; // legal, but dangerous
*((int *) pi) = 5; // equivalent using "C-style" cast
DO NOT USE VOID POINTER !!!
int foo(const vector<int>)
. If the function returns a member of vector
it will be const too.&bsl::ostream operator<<(bsl::osteam& out, const CLASS object&)
Inlining may give the compiler more optimization opportunities
Definition must be visible to clients—not just the declaration; inlines are usually defined in header files Generally cannot set a breakpoint at or in an inlined function
namespace {
using libnlp::attr::TokenClassTag;
using libnlp::attr::TokenClassTagList;
using libnlp::core::Algorithm;
using libnlp::core::AnnotationList;
using libnlp::core::Document;
using libnlp::util::TypeList;
} // namespace
What happens:
int& foo(int a){
return a;
}
cls **ptr = new cls*[10]
delete [] ptr; //destroy all elements in the array
delete ptr; // destroy the array itself
valgrind --leak-check=yes ./*.tsk
can be used to check memory leak.// Read definitions from right to left
T ** a;
T * const *a; // pinter of a const pointer to a T
T const** a; // pointer of pointer to a const T
const T **a; // pointer of pointer to a const T
int (*const a)[3] // an array of 3 const pointers that points to T
int *(*a)[3] // a is a pointer to a array of 3 int pointers
// the parenthesis is to defined the following [3]