C++ smart pointers with no std library - c++

I'm a long time user of the boost::smart_ptr library and love it. Like all boost libraries it is design to work well with the C++ Standard Library. Which usually is a great thing.
Unfortunately, I'm facing a situation were I need to be completely independent of the standard library. Despite this I would need the same kind of functionality as that offered by the boost::smart_ptr (except, obviously every thing that has to do with std::). This includes amongst others, retain count, overloading of the bool and -> operators, relationships between week_ptr and shared_ptr etc.
Has anyone been faced with this situation? I'm looking into using the boost::smart_ptr as a starting point and replacing/eliminating std:: related things. But looking at the complexity, am increasingly concerned about breaking things.

The Loki library may help you, it has a SmartPtr class. It uses std (std::swap, std::runtime_error), but it does not seem to be too hard to get rid of it.

You might be interested in libc++.
This is an implementation of the C++ Standard Library with a liberal license (MIT or BSD-like) so that you can freely pick stuff out of it.
All the stream handling is very complicated (lot of locale stuff), however the STL part (containers and algorithms) as well as part of the numeric stuff (apart from formatting) could work out of the box.
If you need streams, it's a little more involved.
Finally, your biggest issue might come from the exception handling. Note that the Standard Library is normally supposed to work with exceptions enabled (std::out_of_range for example), and exception management is generally based on an external library (for example, see libunwind). Of course, since you reimplement your own library, you can choose to assert instead of throwing.
I would seriously advise not using exceptions as it will be a major pain to make it work on all the devices you care about (it's a bit of a crippled C++ then, but you still get objects and templates).

A classical in reference counting. Some basic code would look like this (shortest code I have managed to produce). Should be straightforward unless you know nothing about reference counting.
template <class CL>
struct refCount {
refCount() : nlinks_(1) , p_(0) {}
refCount(CL*p) : nlinks_(1) , p_(p) {}
~refCount() { if (!nlinks_) delete p_;}
size_t nlinks_;
CL* p_;
};
template <class CL>
class mySmartPtr {
public:
mySmartPtr() : rc_(new refCount<CL>()) {}
mySmartPtr(CL* p) : rc_(new refCount<CL>(p)) {}
mySmartPtr(const mySmartPtr<CL> & otherSmartPtr) : rc_(otherSmartPtr.rc_) { rc_->nlinks_++ ;}
mySmartPtr & operator=(const mySmartPtr<CL> & otherSmartPtr) {
otherSmartPtr.rc_->nlinks_++;
if (!(-- rc_->nlinks_)) delete rc_;
rc_ = otherSmartPtr.rc_;
return *this;}
CL& operator *() {return * rc_->p_ ; }
~mySmartPtr() { if(!(--rc_->nlinks_)) delete rc_;}
// commented to print #links (remove it)
// protected:
refCount<CL> *rc_;
};
A little (big) more work is needed if you need dynamic/static casts (thread safety).
Example of use:
int main()
{
mySmartPtr<int> i;
i = mySmartPtr<int>(new int(1));
*i = 7;
mySmartPtr<int> j(new int(3));
j = i;
std::cout << *j << std::endl ; // prints 7
std::cout << i.rc_->nlinks_ << std::endl ; // prints 2, i and j point to the same
{
mySmartPtr<int> k(j);
std::cout << i.rc_->nlinks_ << std::endl ; // prints 3, k points there two
}
std::cout << i.rc_->nlinks_ << std::endl ; // prints 2 , k gone out of scope
return 0;
}

Related

would exceptions be a reasonable way to return different types?

I've been wondering: since exceptions can be of any type, would they be viable for returning a different type depending on the conditions?
I know it's not very clear so I'll make an example: for a messaging app, we want the users to be able to send their position, but for privacy reasons, we want it to only be shown if the user is online:
void get_user_position(User& u) {
if(!u.is_online()) throw false;
else throw u.get_position();
}
void send_user_position(User& u) {
try {
get_user_position(u);
} catch(bool e) {
//send a message like "user isn't online"
} catch(user_position e) {
//send the position
}
}
This would avoid the need for -1s as failed operation flags and stuff like that. Thoughts? Opinions? Am I completely missing something?
Exceptions should be used for exceptions and not for normal conditional code parts. If "not online" is now an exception is matter of taste.
But if your question is more general and asks about giving back different return types from a single function you should think of using std::variant. With std::holds_alternative you can ask which type was stored in the variant. There are several methods to deal with the content of variants e.g. std::visit
struct A{};
struct B{};
std::variant < A,B > Func( int x)
{
if ( x == 0 ) return A{};
return B{};
}
int main()
{
auto v = Func( 0 );
if ( std::holds_alternative<A>(v) )
{
std::cout << "A" << std::endl;
}
else if ( std::holds_alternative<B>(v) )
{
std::cout << "B" << std::endl;
}
// or even use std::visit or whatever is helpful...
}
Absolutely not. You don't bring a sword to the table to cut vegetables. In this case, its not even a sword. Its a brush.
Jokes apart, looking at what you want to do, this means you already know what possible types of the return value are. Since that's the case, use std::variant.
So long as all the exceptions you use in this way are derived from a common base class, e.g.
struct payload_base_class : public std::exception
{
};
then I can see that this pattern of yours could be useful. I've mandated this commonality so you can distinguish between your return-flavour exceptions over ones that you should treat in a more standard fashion.
(It's possible that you might not want std::exception as the base class, else your exceptions might be caught unintentionally. That's for you to study.)
This technique has an advantage over a std::variant approach in that you can add new return types without having to change the std::variant template; doing that latter can introduce breaking changes.
C++ is designed to allow such exploits. Just because folk didn't have this use-case in mind when exceptions were developed doesn't make this approach illegitimate. Template metaprogamming grew up unintentionaly too.

is the a practical way to emulate GO language defer in C or C++ destructors?

In short: it is a smart pointers in C question. Reason: embedded programming and need to ensure that if complex algorithm is used, then proper deallocation occurs with little effort on the developer side.
My favorite feature of C++ is ability to execute a proper deallocation of object allocated on stack and that goes out of scope. GO language defer provides same functionality and it is a bit closer in spirit to C.
GO defer would be the desired way of doing things in C. Is there a practical way to add such functionality?
The goal of doing so is simplification of tracking when and where object goes out of scope. Here is a quick example:
struct MyDataType *data = malloc(sizeof(struct MyDataType));
defer(data, deallocator);
if (condition) {
// dallocator(data) is called automatically
return;
}
// do something
if (irrelevant) {
struct DT *localScope = malloc(...);
defer(localScope, deallocator);
// deallocator(localScope) is called when we exit this scope
}
struct OtherType *data2 = malloc(...);
defer(data2, deallocator);
if (someOtherCondition) {
// dallocator(data) and deallocator(data2) are called in the order added
return;
}
In other languages I could create an anonymous function inside the code block, assign it to the variable and execute manually in front of every return. This would be at least a partial solution. In GO language defer functions can be chained. Manual chaining with anonymous functions in C is error prone and impractical.
Thank you
In C++, I've seen "stack based classes" that follow the RAII pattern. You could make a general purpose Defer class (or struct) that can take any arbitrary function or lambda.
For example:
#include <cstddef>
#include <functional>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::function;
using std::string;
struct Defer {
function<void()> action;
Defer(function<void()> doLater) : action{doLater} {}
~Defer() {
action();
}
};
void Subroutine(int i) {
Defer defer1([]() { cout << "Phase 1 done." << endl; });
if (i == 1) return;
char const* p = new char[100];
Defer defer2([p]() { delete[] p; cout << "Phase 2 done, and p deallocated." << endl; });
if (i == 2) return;
string s = "something";
Defer defer3([&s]() { s = ""; cout << "Phase 3 done, and s set to empty string." << endl; });
}
int main() {
cout << "Call Subroutine(1)." << endl;
Subroutine(1);
cout << "Call Subroutine(2)." << endl;
Subroutine(2);
cout << "Call Subroutine(3)." << endl;
Subroutine(3);
return EXIT_SUCCESS;
}
Many different answers, but a few interesting details was not said.
Of course destructors of C++ are very strong and should be used very often. Sometime some smart pointers could help you. But the mechanism, that is the most resemble to defer is ON_BLOCK_EXIT/ON_BLOCK_EXIT_OBJ (see http://http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 ). Do not forgot to read about ByRef.
One big difference between C++ and go is when deffered is called. In C++ when your program leaving scope, where is was created. But in go when your program leaving function. That means, this code won't work at all:
for i:=0; i < 10; i++ {
mutex.Lock()
defer mutex.Unlock()
/* do something under the mutex */
}
Of course C does not pretends that is object oriented and therefore there are no destructors at all. It help a lot of readability of code, because you know that your program at line X do only what is written in that line. In contrast of C++ where each closing curly bracket could cause calling of dozens destructors.
In C you can use hated statement goto. Don't use it for anything else, but it is practical to have cleanup label at the end of function call goto cleanup from many places. Bit more complicated is when more than one resource you want do release, than you need more that one cleanup. Than your function finish with
cleanup_file:
fclose(f);
cleanup_mutex:
pthread_mutex_unlock(mutex);
return ret;
}
C does not have destructors (unless you think of the GCC specific variable attribute cleanup, which is weird and rarely used; notice also that the GCC function attribute destructor is not what other languages, C++ notably, call destructor). C++ have them. And C & C++ are very different languages.
In C++11, you might define your class, having a std::vector or std::function-s, initialized using a std::initialized_list of lambda expressions (and perhaps dynamically augmented by some push_back). Then its destructor could mimic Go's defer-ed statements. But this is not idiomatic.
Go have defer statements and they are idiomatic in Go.
I recommend sticking to the idioms of your programming languages.
(In other words: don't think in Go while coding in C++)
You could also embed some interpreter (e.g. Lua or Guile) in your application. You might also learn more about garbage collection techniques and concepts and use them in your software (in other words, design your application with its specific GC).
Reason: embedded programming and need to ensure that if complex algorithm is used, then proper deallocation occurs with little effort on the developer side.
You might use arena-based allocation techniques, and de-allocate the arena when suitable... When you think about that, it is similar to copying GC techniques.
Maybe you dream of some homoiconic language with a powerful macro system suitable for meta-programming. Then look into Common Lisp.
I just implemented a very simple thing like defer in golang several days ago.
The only one behaviour different from golang is my defer will not be executed when you throw an exception but does not catch it at all. Another difference is this cannot accept a function with multiple arguments like in golang, but we can deal it with lambda capturing local variables.
The implementations are here.
class _Defer {
std::function<void()> __callback;
public:
_Defer(_Defer &&);
~_Defer();
template <typename T>
_Defer(T &&);
};
_Defer::_Defer(_Defer &&__that)
: __callback{std::forward<std::function<void()>>(__that.__callback)} {
}
template <typename T>
_Defer::_Defer(T &&__callback)
: __callback{
static_cast<std::function<void()>>(std::forward<T>(__callback))
} {
static_assert(std::is_convertible<T, std::function<void()>>::value,
"Cannot be convert to std::function<void()>.");
}
_Defer::~_Defer() {
this->__callback();
}
And then I defined some macros to make my defer like a keyword in C++ (just for fun)
#define __defer_concatenate(__lhs, __rhs) \
__lhs##__rhs
#define __defer_declarator(__id) \
if (0); /* You may forgot a `;' or deferred outside of a scope. */ \
_Defer __defer_concatenate(__defer, __id) =
#define defer \
__defer_declarator(__LINE__)
The if (0); is used to prevent defer a function out of a scope. And then we can use defer like in golang.
#include <iostream>
void foo() {
std::cout << "foo" << std::endl;
}
int main() {
defer []() {
std::cout << "bar" << std::endl;
};
defer foo;
}
This will print
foo
bar
to screen.
GO defer would be the desired way of doing things in C. Is there a practical way to add such functionality?
The goal of doing so is simplification of tracking when and where object goes out of scope.
C does not have any built-in mechanism for automatically invoking any kind of behavior at the end of an object's lifetime. The object itself ceases to exist, and any memory it occupied is available for re-use, but there is no associated hook for executing code.
For some kinds of objects, that is entirely satisfactory by itself -- those whose values do not refer to other objects with allocated storage duration that need to be cleaned up as well. In particular, if struct MyDataType in your example is such a type, then you get automatic cleanup for free by declaring instances as automatic variables instead of allocating them dynamically:
void foo(void) {
// not a pointer:
struct MyDataType data /* = initializer */;
// ...
/* The memory (directly) reserved for 'data' is released */
}
For objects that require attention at the end of their lifetime, it is generally a matter of code style and convention to ensure that you know when to clean up. It helps, for example, to declare all of your variables at the top of the innermost block containing them, though C itself does not require this. It can also help to structure your code so that for each object that requires custom cleanup, all code paths that may execute during its lifetime converge at the end of that lifetime.
Myself, as a matter of personal best practices, I always try to write any cleanup code needed for a given object as soon as I write its declaration.
In other languages I could create an anonymous function inside the code block, assign it to the variable and execute manually in front of every return. This would be at least a partial solution. In GO language defer functions can be chained. Manual chaining with anonymous functions in C is error prone and impractical
C has neither anonymous functions nor nested ones. It often does make sense, however, to write (named) cleanup functions for data types that require cleanup. These are analogous to C++ destructors, but you must call them manually.
The bottom line is that many C++ paradigms such as smart pointers, and coding practices that depend on them, simply do not work in C. You need different approaches, and they exist, but converting a large body of existing C++ code to idiomatic C is a distinctly non-trivial undertaking.
For those using C, I’ve built a preprocessor in C (open source, Apache license) that inserts the deferred code at the end of each block:
https://sentido-labs.com/en/library/#cedro
GitHub: https://github.com/Sentido-Labs/cedro/
It includes a C utility that wraps the compiler (works out-of-the-box with GCC and clang, configurable) so you can use it as drop-in replacement for cc, called cedrocc, and if you decide to get rid of it, running cedro on a C source file will produce plain C. (see the examples in the manual)
The alternatives I know about are listed in the “Related work” part of the documentation:
Apart from the already mentioned «A defer mechanism for C», there are macros that use a for loop as for (allocation and initialization; condition; release) { actions } [a] or other techniques [b].
[a] “P99 Scope-bound resource management with for-statements” from the same author (2010), “Would it be possible to create a scoped_lock implementation in C?” (2016), ”C compatible scoped locks“ (2021), “Modern C and What We Can Learn From It - Luca Sas [ ACCU 2021 ] 00:17:18”, 2021
[b] “Would it be possible to create a scoped_lock implementation in C?” (2016), “libdefer: Go-style defer for C” (2016), “A Defer statement for C” (2020), “Go-like defer for C that works with most optimization flag combinations under GCC/Clang” (2021)
Compilers like GCC and clang have non-standard features to do this like the __cleanup__ variable attribute.
This implementation avoids dynamic allocation and most limitations of other implementations shown here
#include<type_traits>
#include<utility>
template<typename F>
struct deferred
{
std::decay_t<F> f;
template<typename G>
deferred(G&& g) : f{std::forward<G>(g)} {}
~deferred() { f(); }
};
template<typename G>
deferred(G&&) -> deferred<G>;
#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(x, y)
#define ANONYMOUS_VAR(x) CAT(x, __LINE__)
#define DEFER deferred ANONYMOUS_VAR(defer_variable) = [&]
And use it like
#include<iostream>
int main()
{
DEFER {
std::cout << "world!\n";
};
std::cout << "Hello ";
}
Now, whether to allow exceptions in DEFER is a design choice bordering on philosophy, and I'll leave it to Andrei to fill in the details.
Note all such deferring functionalities in C++ necessarily has to be bound to the scope at which it is declared, as opposed to Go's which binds to the function at which it is declared.

C++ stream second insertion operator

Is it possible to define a second insertion operator to have two modes of outputting a class? Say e.g. one that outputs all members and one that just outputs some basic unique identifier that is grep-able in a log? If so, is there an operator that is usually chosen? I would guess as analogy to << one might use <<< if that is legal?
Thanks
If you want to output only the id, then the best idea is probably to provide a method to get the id in a type that's streamable (e.g. std::string id() const;). That's much more intuitive to other people working on the code than some strange operator use.
Your suggestion of <<< (it's not possible to create new operators in C++, but ignoring that for a moment) reveals that you're happy for there to be different code at the point of call. Therefore, the only benefit you'd get would be the saving of a few character's source code; it isn't worth the obfuscation.
By way of contrast, there are situations where you want the same streaming notation to invoke different behaviours, such as switching between id-only and full data, or different representations such as tag/value, CSV, XML, and binary. These alternatives are usually best communicated by either:
using different stream types (e.g. XMLStream rather than std::ostream), and defining XMLStream& operator<<(XMLStream&, const My_Type&) etc, and/or
using stream manipulators - you can create your own - random Google result: http://www.informit.com/articles/article.aspx?p=171014&seqNum=2
There's no such thing already defined or in use by convention.
Also, you cannot define your own operators in C++, you have to use one of the ones already in the language and overloadable, and <<< isn't an operator in C++, so it is out anyway.
I'd strongly recommend you don't use some other operator for this. (See rule #1 here for a more thorough explanation.) If you have subtle differences between output operations, well-chosen functions names go a long way for making better code than unclear operators arbitrarily picked.
No. You can't define your own operators (<<< doesn't exist in C++). But you can define a id() method returning a string and output this.
There is no such operator as <<< in C++.
You are, however, free to implement, for example operator <(ostream&,Object&), which would do what you want. The problem is, code may get unreadable when you try to chain < and << together.
you can use operator | for instance. Another way of doing this is to define small tag classes for which the operator is overloaded; example (pretty simplistic but you get the point):
template< class T >
struct GrepTag
{
GrepTag( const T& );
T value;
}
template< class T >
Greptag< T > MakeGrepTag( const T& x )
{
return GrepTag< T >( x );
}
template< class T >
MyClass& MyClass::operator << ( const GrepTag< T >& g )
{
//output g.value here
}
MyClass() << MakeGrepTag( "text" );
Yet another way, more like the standard streams, is to use a tag as well but keep some state internally:
struct GrepTag
{
}
MyClass& MyClass::operator << ( const GrepTag& g )
{
grepState = true;
}
template< class T >
MyClass& MyClass::operator << ( const T& )
{
if( grepState )
{
//output special
grepState = false;
}
else
{
//output normal
}
}
MyClass() << GrepTag() << "text";
You cannot define your own operators in C++. You can only overload those that exist.
So I recomend not using an operator for outputting basic unique identifier grep-able in a log. This doesn't correspond to any existing operator role. Use a method instead, such as exportToLog().

C++ string parsing ideas

I have the output of another program that was more intended to be human readable than machine readable, but yet am going to parse it anyway. It's nothing too complex.
Yet, I'm wondering what the best way to do this in C++ is. This is more of a 'general practice' type of question.
I looked into Boost.Spirit, and even got it working a bit. That thing is crazy! If I was designing the language that I was reading, it might be the right tool for the job. But as it is, given its extreme compile-times, the several pages of errors from g++ when I do anything wrong, it's just not what I need. (I don't have much need for run-time performance either.)
Thinking about using C++ operator <<, but that seems worthless. If my file has lines like "John has 5 widgets", and others "Mary works at 459 Ramsy street" how can I even make sure I have a line of the first type in my program, and not the second type? I have to read the whole line and then use things like string::find and string::substr I guess.
And that leaves sscanf. It would handle the above cases beautifully
if( sscanf( str, "%s has %d widgets", chararr, & intvar ) == 2 )
// then I know I matched "foo has bar" type of string,
// and I now have the parameters too
So I'm just wondering if I'm missing something or if C++ really doesn't have much built-in alternative.
sscanf does indeed sound like a pretty good fit for your requirements:
you may do some redundant parsing, but you don't have performance requirements prohibiting that
it localises the requirements on the different input words and allows parsing of non-string values directly into typed variables, making the different input formats easy to understand
A potential problem is that it's error prone, and if you have lots of oft-changing parsing phrases then the testing effort and risk can be worrying. Keeping the spirit of sscanf but using istream for type safety:
#include <iostream>
#include <sstream>
// Str captures a string literal and consumes the same from an istream...
// (for non-literals, better to have `std::string` member to guarantee lifetime)
class Str
{
public:
Str(const char* p) : p_(p) { }
const char* c_str() const { return p_; }
private:
const char* p_;
};
bool operator!=(const Str& lhs, const Str& rhs)
{
return strcmp(lhs.c_str(), rhs.c_str()) != 0;
}
std::istream& operator>>(std::istream& is, const Str& str)
{
std::string s;
if (is >> s)
if (s.c_str() != str)
is.setstate(std::ios_base::failbit);
return is;
}
// sample usage...
int main()
{
std::stringstream is("Mary has 4 cats");
int num_dogs, num_cats;
if (is >> Str("Mary") >> Str("has") >> num_dogs >> Str("dogs"))
{
std::cout << num_dogs << " dogs\n";
}
else if (is.clear(), is.seekg(0), // "reset" the stream...
(is >> Str("Mary") >> Str("has") >> num_cats >> Str("cats")))
{
std::cout << num_cats << " cats\n";
}
}
The GNU tools flex and bison are very powerful tools you could use that are along the lines of Spirit but (according to some people) easier to use, partially because the error reporting is a bit better since the tools have their own compilers. This, or Spirit, or some other parser generator, is the "correct" way to go with this because it affords you the greatest flexibility in your approach.
If you're thinking about using strtok, you might want to instead take a look at stringstream, which splits on whitespace and lets you do some nice formatting conversions between strings, primitives, etc. It can also be plugged into the STL algorithms, and avoids all the messy details of raw C-style string memory management.
I've written extensive parsing code in C++. It works just great for that, but I wrote the code myself and didn't rely on more general code written by someone else. C++ doesn't come with extensive code already written, but it's a great language to write such code in.
I'm not sure what your question is beyond just that you'd like to find code someone has already written that will do what you need. Part of the problem is that you haven't really described what you need, or asked a question for that matter.
If you can make the question more specific, I'd be happy to try and offer a more specific answer.
I've used Boost.Regex (Which I think is also tr1::regex). Easy to use.
there is always strtok() I suppose
Have a look at strtok.
Depending on exactly what you want to parse, you may well want a regular expression library.
See msdn or earlier question.
Personally, again depending the exact format, I'd consider using perl to do an initial conversion into a more machine readable format (E.g. variable record CSV) and then import into C++ much more easily.
If sticking to C++, you need to:
Identify a record - hopefully just a
line
Determine the type of the record - use regex
Parse the record - scanf is fine
A base class on the lines of:
class Handler
{
public:
Handler(const std::string& regexExpr)
: regex_(regexExpr)
{}
bool match(const std::string& s)
{
return std::tr1::regex_match(s,regex_);
}
virtual bool process(const std::string& s) = 0;
private:
std::tr1::basic_regex<char> regex_;
};
Define a derived class for each record type, stick an instance of each in a set and search for matches.
class WidgetOwner : public Handler
{
public:
WidgetOwner()
: Handler(".* has .* widgets")
{}
virtual bool process(const std::string& s)
{
char name[32];
int widgets= 0;
int fieldsRead = sscanf( s.c_str(), "%32s has %d widgets", name, & widgets) ;
if (fieldsRead == 2)
{
std::cout << "Found widgets in " << s << std::endl;
}
return fieldsRead == 2;
}
};
struct Pred
{
Pred(const std::string& record)
: record_(record)
{}
bool operator()(Handler* handler)
{
return handler->match(record_);
}
std::string record_;
};
std::set<Handler*> handlers_;
handlers_.insert(new WidgetOwner);
handlers_.insert(new WorkLocation);
Pred pred(line);
std::set<Handler*>::iterator handlerIt =
std::find_if(handlers_.begin(), handlers_.end(), pred);
if (handlerIt != handlers_.end())
(*handlerIt)->process(line);

Making the leap from Java to C++

As the topic says I'm very new to c++, but I have some experience with java.
To start learning c++ I had the (not very original) idea of making a simple command line calculator.
What I'm trying to do is store the numbers and operators in a binary tree.
#include <iostream>
using namespace std;
class Node
{
bool leaf;
double num;
char oper;
Node* pLNode;
Node* pRNode;
public:
Node(double n)
{
num = n;
leaf = true;
pLNode = 0;
pRNode = 0;
}
Node(char o, Node lNode, Node rNode)
{
oper = o;
pLNode = &lNode;
pRNode = &rNode;
leaf = false;
}
bool isLeaf()
{
return leaf;
}
double getNumber()
{
return num;
}
char getOperator()
{
return oper;
}
Node* getLeftNodePointer()
{
return pLNode;
}
Node* getRightNodePointer()
{
return pRNode;
}
//debug function
void dump()
{
cout << endl << "**** Node Dump ****" << endl;
cout << "oper: " << oper << endl;
cout << "num: " << num << endl;
cout << "leaf: " << leaf << endl;
cout << "*******************" << endl << endl;
}
};
class CalcTree
{
Node* pRootNode;
Node* pCurrentNode;
public:
Node* getRootNodePointer()
{
return pRootNode;
}
Node* getCurrentNodePointer()
{
return pCurrentNode;
}
void setRootNode(Node node)
{
pRootNode = &node;
}
void setCurrentNode(Node node)
{
pCurrentNode = &node;
}
double calculateTree()
{
return calculateTree(pRootNode);
}
private:
double calculateTree(Node* nodePointer)
{
if(nodePointer->isLeaf())
{
return nodePointer->getNumber();
}
else
{
Node* leftNodePointer = nodePointer->getLeftNodePointer();
Node* rightNodePointer = nodePointer->getRightNodePointer();
char oper = nodePointer->getOperator();
if(oper == '+')
{
return calculateTree(leftNodePointer) + calculateTree(rightNodePointer);
}
else if(oper == '-')
{
return calculateTree(leftNodePointer) - calculateTree(rightNodePointer);
}
else if(oper == '*')
{
return calculateTree(leftNodePointer) * calculateTree(rightNodePointer);
}
else if(oper == '/')
{
return calculateTree(leftNodePointer) / calculateTree(rightNodePointer);
}
}
}
};
int main(int argc, char* argv[])
{
CalcTree tree;
tree.setRootNode(Node('+', Node(1), Node(534)));
cout << tree.calculateTree() << endl;
return 0;
}
I've got a couple of questions about this code:
This compiles but does not do what's intended. It seems that after tree.setRootNode(Node('+', Node(1), Node(534))); in main, the rightnode is initialized properly but the leftnode isn't. Compiling and running this prints out 534 for me (gcc, freebsd). What is wrong here?
It seems in c++ people prefer to define members of a class outside the class, like
class A
{
public:
void member();
};
A :: member(){std::cout << "Hello world" << std::endl;}
why is that?
I'd very much like some pointers on c++ conventions (naming, indenting etc.)
I'm used to coding java with eclipse. Atm I'm using emacs for learning c++. Can someone advise me on a good (free) c++ ide, or should I stfu and stick with emacs like a real man? :)
First, I can only recommend to have a look at the book "Accelerated C++". It will jump-start you into STL, and C++ style, and can save you a year of bad experiences. (There is quite an amount of extraordinary well written literature on C++ out there, if you decide to go deeper).
C++ does not use automatic memory management on the heap. You are storing pointers to temporaries. Your program is incorrect as it tries to access destructed objects. Like it or not, you'll have to learn on object lifetime first. You can simplify a good part of this in simple cases by using value semantics (not storing pointers, but storing a copy of the object).
Eclipse/CDT is reported to be quite OK on linux. On Windows you'll do easier with Microsoft Visual C++ Express Edition. When you've gotten into the basics, switching later will be no problem for you.
Defining members outside of the class itself is preferred as we usually split header and implementation files. In the header you try not to expose any unnecessary information, and also to reduce code-size, it's a simple matter of compile time. But for many modern programming techniques (like using template meta-programming) this cannot be used, so quite some C++ code moves in the direction of inline definitions.
First, i recommend you a good book too. There are very good SO threads about C++ books, like The definitive C++ book guide and List. In the following, you find i tell you how to solve some problems, but i don't delve into details, because i think that's what a book can do much better.
I've glanced over the code, here is what i've figured:
Node(char o, Node lNode, Node rNode)
{
oper = o;
pLNode = &lNode;
pRNode = &rNode;
leaf = false;
}
That constructor has 3 parameters, all of which are local to the function. When the function returns, the parameters do not exist anymore, and their memory occupied by them is cleaned up automatically. But you store their addresses into the pointers. That will fail then. What you want is passing pointers. By the way always use constructor initializer lists:
Node(char o, Node *lNode, Node *rNode)
:oper(o), pLNode(lNode), pRNode(rNode), leaf(false)
{ }
Creating the tree now does look different:
CalcTree tree;
tree.setRootNode(new Node('+', new Node(1), new Node(534)));
cout << tree.calculateTree() << endl;
New creates a dynamic object and returns a pointer to it. The pointer must not be lost - otherwise you have a memory-leak because you can't delete the object anymore. Now, make sure you delete child nodes ordinarily by creating a destructor for Node (put it as you would put any other member function):
~Node() {
delete pLNode;
delete pRNode;
}
Here you see it's important to always null-ify pointers: delete on a null pointer will do nothing. To start cleaning-up, you create a CalcTree destructor too, which starts the delete chain:
~CalcTree() {
delete pRootNode;
}
Don't forget to create a default constructor for CalcTree that initializes that pointer to 0! Now, you have one remaining problem: If you copy your object, the original object and the copy share the same pointer, and when the second object (the copy) goes out of scope, it will call delete on the pointer a second time, thus deleting the same object twice. That's unfortunate. It can be solved by forbidding copying your classes - or by using smart pointers that have shared ownership semantics (look into shared_ptr). A third variant is to write your own copy constructor and copy assignment operator. Well, here is how you would disable copy constructor and copy assignment operators. Once you try to copy, you will get a compile error. Put this into Node:
private:
Node(Node const&);
Node& operator=(Node const&);
The same for CalcTree, and you are protected from that subtle bug now.
Now, onto your other questions:
It seems in c++ people prefer to define members of a class outside the class
That is because the more code you add to the header, the more you have to include into your header from other files (because your code depends on something that's defined in them). Note that all other files that include that header then will transitively include the headers that one includes too. So you will in the end have less indirectly included headers when you put your code into separately compiled files instead. Another problem that is solved are cyclic references. Sometimes, you have to write a method that needs to have access to something defined later in the header. Since C++ is a single-pass language, the compiler can't resolve references to symbols that are declared after the point of use - generally.
I'd very much like some pointers on c++ conventions
That's very subjective, but i like this convention:
Class data-members are written like mDataMember
Function are written like getDataMember
Local variables are written like localVariable
Indenting with spaces, 4 spaces each (uh oh, this one is controversial. There are many possible ways to indent, please do not ask for the best one!)
I'm used to coding java with eclipse. Atm I'm using emacs for learning c++.
I'm using emacs for my C++ development, and eclipse for Java. Some use eclipse for Java too (there is a package called CDT for eclipse C++ development). It seems to be quite common gist (i agree) that Visual C++ on windows is the best IDE you get for windows. There are also some answers on SO regarding this: Best IDE for C++ (best search with google in stackoverflow, it will give you much more results than the builtin search).
You're passing by value, not by reference when you say
Node(char o, Node lNode, Node rNode)
It should be
Node(char o, Node &lNode, Node &rNode)
or better yet (for consistency with the rest of your code),
Node(char o, Node *lNode, Node *rNode)
Compilation speed: The header (.h file) contains extra information not embedded in the .o files, so it must be recompiled by every other C++ file that includes it. Space: If you include method bodies, they are duplicated in every file that includes the .h file. This is in contrast to Java, where all of the relevant information is embedded in the .class file. C++ cannot do this because it is a much richer language. In particular, macros make it so that C++ will never be able to embed all the information in a .o file. Also, Turing-complete templates make it challenging to get rid of the .h / .cpp distinction.
There are many conventions. The standard C++ library has one set, the standard C library has another, BSD and GNU each have their own, and Microsoft uses yet another. I personally like to be fairly close to Java when it comes to naming identifiers and indenting.
Eclipse, NetBeans, KDevelop, vim, and emacs are all good options. If you're on Windows, Visual Studio is really nice.
There are very different conventions for C++. Google some. There is no "official" convention. ;)
To your IDE question: I am using the CDT (C[/C++] Development Tools, Eclipse). There has been a first release for another Eclipse based C++ IDE: http://www.eclipse.org/linuxtools/ I am going to test it out these days. Sounds very good.
Also try out KDevelop if you are using KDE.
2. It seems in c++ people prefer to define members of a class outside the
class[..]
It's a matter of style. Mostly. We group the big bulky methods in a separate cpp file, and keep the small ones along with the header file. Declaring the method within the class declaration makes the function inline (which is a hint for the compiler to do, you guessed it -- inlining). This is something you may or may not want depending on the problem you want to solve.
3. I'd very much like some pointers on c++ conventions (naming, indenting etc.)
The standard library is a good reference. Start looking at the headers.
4. I'm used to coding java with eclipse.
Eclipse can be configured to use a C++ compiler. Go(ogle) for it, please. Why punish yourself twice now that you've taken to C++ ;-)