CPP notes
From OriWiki
Contents |
get environment variables
#include <cstdlib> int main() { const char *str = std::getenv("PATH"); std::cout << "PATH:" << str << '\n'; }
define a macro in the compilation command
#include <iostream>
int main() {
std::cout << MYDEF << '\n';
}
g++ -Wall -DMYDEF=17 check.cpp -o check
g++ -Wall -D'MYDEF="hello lord"' check.cpp -o check
this->data at initialization list
The following doesnot compile and put a question whether I should use the this->dataMember syntax
#include <iostream>
class A {
public:
int m_data;
A()
:m_data(5) // the following doesn't compile: (this->m_data)(5)
{
std::cout << this->m_data << "\n";
}
};
int main() {
A a;
}
std::set
#include <iostream>
#include <set>
#include <string>
#include <algorithm>
#include <iterator>
typedef std::set<std::string> Set;
int main() {
Set s;
s.insert("hey"); s.insert("hello"); s.insert("bye");
copy(s.begin(),s.end(),std::ostream_iterator<std::string> (std::cout,"\n"));
s.erase("hello");
copy(s.begin(),s.end(),std::ostream_iterator<std::string> (std::cout,", "));
std::cout << "main done.\n";
}
ldd
ldd - list dynamic dependencies
list the linked stuff
ldd <executable>
Makefile
A minimal skeleton
Objs = main.o f1.o main: $(Objs) g++ $(Objs) -o $@ %.o: %.cpp g++ -Wall -c $< depend: echo -e '\n' >> Makefile g++ -MM *.cpp >> Makefile clean: rm *.o
alternative syntax for the general rule:
.cpp.o: g++ -Wall -c $<
Meta makefile
Assuming two subdirectories proj1 and proj1 that contain projects
all: make -C proj1 make -C proj2 clean: make -C proj1 clean make -C proj2 clean run: ./proj1/main ./proj2/main
uri was here
using libraries
A guide from the labc course at the university.
static library makefile skeleton
In the library directory
Objs = f1.o f2.o libmine.a : $(Objs) ar rc $@ $(Objs) ranlib $@ .cpp.o: g++ -Wall -c $<
In the using directory
using_static_lib: using_static_lib.o g++ using_static_lib.o -L../static_lib -lmine -o $@ using_static_lib.o: using_static_lib.cpp g++ -Wall -I../static_lib -c $<
shared library makefile skeleton
Objs = f1.o f2.o libmine.so : $(Objs) g++ -shared $(Objs) -o $@ .cpp.o: g++ -Wall -fPIC -c $<
In the using directory
using_shared_lib: using_shared_lib.o
g++ $< -L ../shared_lib -lmine -o $@
using_shared_lib.o: using_shared_lib.cpp
g++ -Wall -I ../shared_lib -c $<
# note you should add the library directory to the LD_LIBRARY_PATH environment
# variable
# LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:`pwd`/../shared_lib
Exception Handling
Note that each throw copies the thrown object into a dedicated place:
#include <iostream>
#include <string>
using namespace std;
class A {
string m_str;
public:
A(string str): m_str(str) { std::cout << "A(), "<<m_str<<"\n"; }
~A() { std::cout << "~A(), " <<m_str << "\n"; }
A(const A& other):m_str("copy "+other.m_str) {
std::cout << "A(const A&), "<<m_str <<"\n";
}
};
int main() {
std::cout << "start...\n";
try {
A a("local");
throw a;
} catch (A a) {
std::cout << "catch\n";
}
std::cout << "done.\n";
}
Output:
start... A(), local A(const A&), copy local ~A(), local A(const A&), copy copy local catch ~A(), copy copy local ~A(), copy local done.
It seems like the compiler (at least the compilers I've checked) performs an optimization when throwing an annonimous object:
int main() {
std::cout << "start...\n";
try {
throw A("local");
} catch (A a) {
std::cout << "catch\n";
}
std::cout << "done.\n";
}
Output
start... A(), local A(const A&), copy local catch ~A(), copy local ~A(), local done.
The sending of the parameter by name can also be saved if a refference is cought:
int main() {
std::cout << "start...\n";
try {
throw A("local");
} catch (A& a) {
std::cout << "catch\n";
}
std::cout << "done.\n";
}
Output
start... A(), local catch ~A(), local done.
template stuff
It seems like there is a strange behavior of g++-3.4 stuff that is related to friend of template function declaration. See how I managed to get the following code to compile only after putting the implementation before the declaration (which required a forward declaration)
#include <iostream>
template <typename T>
class A;
template <typename T>
std::ostream& operator<< (std::ostream& os, const A<T>& a) {
return os << a.m_data;
}
template <typename T>
class A {
friend std::ostream& ::operator << <>(std::ostream& os, const A& a);
T m_data;
public:
A(T data):m_data(data) {}
};
int main() {
A<std::string> a("hello");
std::cout << a << '\n';
}
My smart ptr sample code
The reference counter is implemented as a dynamically allocated int that is pointed from the My_Ptr object (m_rc). A NULL My_Ptr is represented with both m_ptr and m_rc equal to NULL.Note that the dec() function is the one that performs the deletion.
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class My_Ptr;
template <typename T>
ostream& operator<<(ostream& os, const My_Ptr<T>& ptr) {
os << ptr.m_ptr << " RC:";
if(ptr.m_rc)
os << *(ptr.m_rc);
else
os << "NULL";
return os;
}
template <typename T>
class My_Ptr {
friend ostream& operator<< <>(ostream& os, const My_Ptr& ptr);
T *m_ptr;
int *m_rc;
void inc() {
if(!m_rc)
return;
++(*m_rc);
}
void dec() {
if(!m_rc)
return;
--(*m_rc);
if(*m_rc == 0) {
delete m_rc;
delete m_ptr;
m_ptr = NULL;
m_rc = NULL;
}
}
public:
My_Ptr():m_ptr(NULL),m_rc(NULL) {}
My_Ptr(T* ptr): m_ptr(ptr),m_rc(new int(1)) {}
My_Ptr(const My_Ptr<T>& other): m_ptr(other.m_ptr), m_rc(other.m_rc) { inc(); }
~My_Ptr() { dec(); }
void operator =(My_Ptr<T>& other) {
other.inc(); //
dec(); // order matters for p=p case
m_rc = other.m_rc;
m_ptr = other.m_ptr;
}
};
class A {
string m_data;
public:
A(string data):m_data(data) { cout << "A(), " << m_data << '\n'; }
~A() { cout << "~A(), " << m_data << '\n'; }
};
int main() {
My_Ptr<A> p, pp(new A("***"));
{
My_Ptr<A> p1(new A("@@@"));
p = p1;
cout << "1 " << p << " " << p1 << '\n';
{
My_Ptr<A> p2(p1);
cout << "2 " << p << " " << p1 << " " << p2 << '\n';
}
cout << "3 " << p << " " << p1 << '\n';
}
pp = p;
std::cout << "4 " << p << '\n';
}
(this code seems to give similar functionality as boost::shared_ptr [1])
enum
Usual definition
enum Day_t {
Sunday,
Monday,
Tuesday,
DAY_T_LAST,
};
int main() {
Day_t day;
day = Monday;
int N = DAY_T_LAST;
std::cout << "there are " << N << " days. day=" << day << '\n';
}
I've seen codes that add a typedef before:
typedef enum Day_t {...};
Which seems to have no effect.
view symbols in shared object
nm libmylib.so

