A pointer can receive a NULL parameter, a reference parameter can not. If there's ever a chance that you could want to pass "no object", then use a pointer instead of a reference.
Also, passing by pointer allows you to explicitly see at the call site whether the object is passed by value or by reference:
// Is mySprite passed by value or by reference? You can't tell
// without looking at the definition of func()
func(mySprite);
// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);
2. Read following code and write the output result
1: int _tmain()
2: {
3: char s[256];
4: char *p =s;
5: p = "some new string";
6: cout<<s<<endl;
7: cout<<*s<<endl;
8: cout<<*(s+2)<<endl;
9: cout<<&p<<endl;
10: cout<<*p<<endl;
11: cout<<*(p+2)<<endl;
12: return 0;
13: }
Output:
any string in memeory
empty
empty
0080F820
s
m
3. Interface VS abstract class in C++
An interface is a contract, you can implement few interfaces for one class. As oppose to abstract class, you can extend only one. So, if you want to communicate with few programs interface would help you, like (in java) comparable and something else. And in C++, it doesn't have Interface key word, only pure virtual methods
The advantage of abstract class is that you can already implement the methods that are relevant for that class. So, when you inherit that class you will already have these methods without the need to duplicate the code if you use an interface.
4. new VS malloc in C++
From the C++ FQA Lite:
[16.4] Why should I use new instead of trustworthy old malloc()?
FAQ: new/delete call the constructor/destructor; new is type safe, malloc is not; new can be overridden by a class.
FQA: The virtues of new mentioned by the FAQ are not virtues, because constructors, destructors, and operator overloading are garbage (see what happens when you have no garbage collection?), and the type safety issue is really tiny here (normally you have to cast the void* returned by malloc to the right pointer type to assign it to a typed pointer variable, which may be annoying, but far from "unsafe").
Oh, and using trustworthy old malloc makes it possible to use the equally trustworthy & old realloc. Too bad we don't have a shiny new operator renew or something.
Still, new is not bad enough to justify a deviation from the common style used throughout a language, even when the language is C++. In particular, classes with non-trivial constructors will misbehave in fatal ways if you simply malloc the objects. So why not use new throughout the code? People rarely overload operator new, so it probably won't get in your way too much. And if they do overload new, you can always ask them to stop.
5. How to implement c++ smart pointer?
http://www.codeproject.com/Articles/15351/Implementing-a-simple-smart-pointer-in-c
6. Pro and Cons of multi-process and multi-thread?
So the key difference between processes and threads is the way memory is managed. This has several implications, the two of the most most important are:
- Inter-thread communication is fast
- There is no protection between threads
Since processes do not naturally share memory it is difficult for one process to communicate with another. Several Inter-Process Communications (IPC) methods exist but they all rely on passing data via some intermediary such as the file system or network stack. Ultimately the kernel manages communications between them.
Threads, on the other hand, can communicate directly using shared memory objects such as arrays of data (buffers).
The disadvantage of threads is the classic problem faced by engineers used to RTOS's and that is the fact that a bug in one thread can corrupt the memory being used by another thread. When a thread crashes it is natural to start debugging that thread but it may well be that the bug is in code utilised only by another thread. These issues can be very difficult to track down!
So when designing an application to exploit the parallel capability of hardware it may seem that the decision is one of performance over protection and debug-ability. But it is not always so simple.
You could have a fast web server, making heavy use of the threaded capability of the OS, but it is unlikely that you will have many customers if they are running an on-line sales system. Why? Simply that any exploitable defect could enable an attacker to read the credit card data from another user - remember that the memory for the thread handling that transaction is readable by the thread handling the attackers connection.
7. Virtual destructor in C++, why need this?
Virtual destructors are useful when you can delete an instance of a derived class through a pointer to base class:
If you want to prevent the deletion of an instance through a base class pointer, you can make the base class destuctor protected and nonvirtual; by doing so, the compiler won't let you call delete on a base class pointer.
class Base
{
// some virtual methods
};
class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
}
Here, you'll notice that I didn't declare Base's destructor to be virtual. Now, let's have a look at the following snippet:Base *b = new Derived();
// use b
delete b; // Here's the problem! Since Base's destructor is not virtual,
// it's ~Base that is called and not ~Derived. Therefore, all the important
// cleanup is not performed, which can create several resource leaks
To sum up, always make base classes' destructors virtual when they're meant to be manipulated polymorphically.If you want to prevent the deletion of an instance through a base class pointer, you can make the base class destuctor protected and nonvirtual; by doing so, the compiler won't let you call delete on a base class pointer.
8. Implement Lock in c++
C# fans like to point out how the language offers nice syntax for often-used constructs, such as protecting a certain block of code with a lock:
lock (m_mutex)
{
// my protected code here
}
C++ doesn't have a
lock
keyword, but you can make one yourself. Given a Mutex
class which has Lock()
and Unlock()
member functions (and perhaps an IsLocked()
for convenience) most C++ programmers would immediately write anAutoLock
, somewhat like this:class AutoLock
{
public:
AutoLock(Mutex& m): m_mutex(m) { m_mutex.Lock(); }
~AutoLock() { m_mutex.Unlock(); }
operator bool() { return m_mutex.IsLocked(); }
private:
Mutex& m_mutex;
};
Normal use of this thing would look like this:
{
AutoLock lock(m_mutex);
// my protected code here
}
But with a simple preprocessor trick you can make the syntax identical to C#:
#define lock(x) if (!(AutoLock _l = x)); else
9. Optimize memcpy
There is a good article about this implementation: http://www.danielvik.com/2010/02/fast-memcpy-in-c.html, which provide a solution as below:
void* memcpy(void* dest, const void* src, size_t count) {
char* dst8 = (char*)dest;
char* src8 = (char*)src;
while (count--) {
*dst8++ = *src8++;
}
return dest;
}
char* dst8 = (char*)dest;
char* src8 = (char*)src;
while (count--) {
*dst8++ = *src8++;
}
return dest;
}
But this is not good enough, we don't need to use char* here.
void * memcpy(void * dst, void const * src, size_t len)
{
long * plDst = (long *) dst;
long const * plSrc = (long const *) src;
if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC))
{
while (len >= 4)
{
*plDst++ = *plSrc++;
len -= 4;
}
}
char * pcDst = (char *) plDst;
char const * pcDst = (char const *) plSrc;
while (len--)
{
*pcDst++ = *pcSrc++;
}
return (dst);
}
10. Copy constructor vs assignment operation
Copy constructor is called when a new object is created from an existing object, as a copy of the existing object (see this G-Fact). And assignment operator is called when an already initialized object is assigned a new value from another existing object.
t2 = t1; // calls assignment operator, same as "t2.operator=(t1);" Test t3 = t1; // calls copy constructor, same as "Test t3(t1);" |
11.