#include <iostream>
#include <algorithm>
#include <iterator>
struct g
{
g():n(0){}
int operator()() { return n++; }
int n;
};
int main()
{
int a[10];
std::generate(a, a+10, g());
std::copy(a, a+10, std::ostream_iterator<int>(std::cout, " "));
}
#include <cstring>
struct S
{
float f;
char c;
int i;
};
int main()
{
S s1 = { 1.1f, 'a', 99 };
S s2 = { 1.1f, 'a', 99 };
bool bSame = memcmp(&s1, &s2, sizeof(S)) == 0;
}
int main(){}
char * p = "foobar";
char const * p = "foobar";
char const s[] = "foobar";
struct Foo
{
void func(){}
};
typedef void (Foo::*func_t)();
int main()
{
func_t fp1 = func_t(&Foo::func);
void * p = (void*) fp1;
func_t fp2 = (func_t) p;
Foo foo;
(foo.*fp2)();
}
int i = 0;
char a[2] = { char() };
a[i++] = ++i;
string s("hallo,world");
char * p = &s[0];
p[1] = 'e';
namespace { std::string const GLOBAL_VAL("some value"); }
// Translation unit "foo.cpp"
int const FOO = 1;
// Translation unit "bar.cpp"
#include "foo.h" // declares int FOO
int const BAR = FOO
// Translation unit "foo.cpp"
int const FOO() { static int const FOO_ = 1; return FOO_; }
// Translation unit "bar.cpp"
#include "foo.h" // declares int FOO()
int const BAR = FOO()
Foo f(Bar());
typedef std::vector<int> vec_t;
vec_t v(100);
vec_t::const_iterator i = v.begin() + 50;
v.push_back(5);
(*i) = 5;
std::auto_ptr<int> pInt = new int;
std::auto_ptr<int> pInt(new int);
std::auto_ptr<int> pInt(new int[10]);
std::string foo() throw()
{
std::string s("hello world");
return s;
}
// Example of RVO
Bar Foo()
{
return Bar();
}
// Example of NRVO
Bar Foo()
{
Bar bar;
return bar;
}
// Snippet 1
struct Bar{};
Bar foo(){ return Bar(); }
Bar & b = foo();
// Snippet 2
struct Bar{};
void foo(Bar & b){ }
int main()
{
foo(Bar());
}
template <typename T> struct A{};
template <typename T> struct B : A<T>{};
template <template <typename> class C, typename T>
C<T> foo()
{
C<T> ct;
return ct;
}
int main()
{
A<int> const & a = foo<B, int>();
}
struct Foo
{
virtual size_t func(size_t st = 0) const = 0;
};
struct Bar : Foo
{
virtual size_t func(size_t st = 999) const
{
return st;
}
};
int main()
{
Foo const & foo = Bar();
size_t st = foo.func(); // What value does st have?
}
struct Bar
{
template <typename U>
void func() const { }
template <typename U>
static void sfunc() { }
};
template <typename T>
void Foo1(T const & t)
{
t.func<int>();
T::sfunc<int>();
}
template <typename T>
void Foo2(T const * pT)
{
pT->func<int>();
}
int main()
{
Bar bar;
Foo1(bar);
Foo2(&bar);
}
struct Bar
{
template <typename U>
void func() const { }
template <typename U>
static void sfunc() { }
};
template <typename T>
void Foo1(T const & t)
{
t.template func<int>(); //<--- The compiler doesn't know what t is, so you need to tell it that it's a template type
T::template sfunc<int>(); //<--- The compiler doesn't know what T is, so you need to tell it that it's a template type
}
template <typename T>
void Foo2(T const * pT)
{
pT->template func<int>(); //<--- The compiler doesn't know what pT is, so you need to tell it that it's a template type
}
int main()
{
Bar bar;
Foo1(bar);
Foo2(&bar);
}
std::string str = "HELLO WORLD";
std::transform(str.begin(), str.end(), str.begin(), tolower);
Foo foo1 = new Foo;
Foo foo2 = new Foo();
void reverse_single_linked_list(struct node** headRef);
T
void reverse_single_linked_list(struct node** headRef)
{
struct node* result = NULL;
struct node* current = *headRef;
struct node* next;
while (current != NULL)
{
next = current->next; // tricky: note the next node
current->next = result; // move the node onto the result
result = current;
current = next;
}
*headRef = result;
}
#define SEALED(className) \
className ## Sealer \
{ \
private: className ## Sealer(){}; \
friend class className; \
}; \
class className : virtual private className ## Sealer \
class SEALED(MyClass) {};
class MyClassDisallowed : public MyClass {};
int main()
{
// Perfectly legal construction
MyClass myClass;
// Illegal construction, super-class is sealed
MyClassDisallowed myClassDisallowed;
}
#include <iostream>
// Some types
struct A{};
struct B:A{};
struct C{};
template <typename T1, typename T2>
struct is_convertible
{
private:
struct True_ { char x[2]; };
struct False_ { };
static True_ helper(T2 const &);
static False_ helper(...);
public:
static bool const YES = (
sizeof(True_) == sizeof(is_convertible::helper(T1()))
);
};
template <typename T1, typename T2>
void foo(T1 const & t1, T2 const & t2)
{
if(is_convertible<T1, T2>::YES)
{
std::cout << "Type t1 is convertible to t2" << std::endl;
}
else
{
std::cout << "Type t1 is not convertible to t2" << std::endl;
}
}
int main(void)
{
struct A a;
struct B b;
struct C c;
foo(b,a);
foo(c,a);
}
template <bool B>
in-line void STATIC_ASSERT_IMPL()
{
// B will be true or false, which will implicitly convert to 1 or 0
char STATIC_ASSERT_FAILURE[B] = {0};
}
#define STATIC_ASSERT(B) STATIC_ASSERT_IMPL <B>()
int main()
{
// On a Windows 32 bit platform with Visual Studio 2005 this will not fail
STATIC_ASSERT(sizeof(int) == 4);
// On a Windows 32 bit platform with Visual Studio 2005 this *will* fail
STATIC_ASSERT(sizeof(int) == 3);
}
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (16)
Commented:
For interviews, my experience has been that questions with open ended answers are much more useful than tedious syntax questions. I'll give examples below of how your quiz could be modified for this.
Question #1. The code style is typical K&R succinct. Anyone in my group who wrote this would fail the coding standards. Putting g():n(0){} all on one line, with no whitespace, makes it very hard to read. There's no differentiation of member variable names. A struct is used for a class definition. All of these are legal C++, but that doesn't make them good code.
All of which points out the value of a discussion of how this code could be improved, particularly the use of complicated constructs for a simple result.
Question #2 (bSame). I liked this question. It's something developers should certainly have run into in their career. However, in terms of testing for "real world" competence, I would change the second "1.1f" to be "2.2f/2". Then you can have a discussion of floating point issues as well as seeing if they can find the more subtle problem.
Other avenues to explore include knowledge of compiler-dependent fixes (#pragma pack, for example), RISC issues (non-aligned accesses aren’t allowed), and cross-platform binary compatibility (such as when writing data files).
Question #3. Fun for trivia, not for interviews, particularly for Windows developers who probably haven't seen a main() function in years.
Question #4, 2 lines of code differ. Consider more issues - the first statement takes seven bytes, or maybe eight with padding. The second statement takes 11 (or 12, or 15, or 16.) The discussion of pointer storage allocation versus an implicit pointer is something that a lot of experienced developers never do understand. In addition, this would be an opportunity to have a discussion of the dangers of fixed-size buffers versus using a class like "string".
Question #5. Good for a discussion of C++ features to avoid. I've used pointers to member functions twice in my career and regretted it both times. I've never had a developer who was able to justify usage of this construct in a code review.
Question #8. I worried about memory exhaustion 20 years ago on systems with 256KB of memory. In this day and age, if your system is that low on memory, an exception from an app failing to initialize its globals is the least of your problems. Consider the odds of this happening versus the odds of introducing a regression by having dozens of functions that declare static variables, check memory, add exception handlers, call the error display routines, etc. Not to mention the cost of unit testing functions over years of releases. Now we are talking about something that's really useful - engineering design decisions affecting testing, production costs, maintainability, etc.
Question #9, "2 lines of code differ". The discussion about the coding technique is most useful in an interview. For example - why aliasing is bad, whether a constant should be hardcoded, put in a database, added to an admin screen, etc. How to pick defaults. Whether a const expression should be all caps in the coding standard (as opposed to a #define.)
Question 10 - Great question.
Question #? - RVO vs. NRVO - I had some interesting discussions with other senior developers about asking candidates about acronyms and buzzwords (like "internal linkage") in interviews. There was general consensus that you didn't need to know most of these to do your job. Even among our highest levels of engineers, there were only a few people assigned to be specialists in C++. Others had specialties in other areas. In any case, for these two particular terms, you are getting into hardcore optimization. In general, the rule is "Optimize Last". I don't want developers worrying about this low level material when they are writing an error handling function that returns a string once per year. For interviews, that would be a much more interesting discussion than whether they know these acronyms.
Thanks again!
Author
Commented:Thanks for your feedback.
Commented:
Commented:
Great post. Well though out. This piece reminds me when I was starting out C++ Q & A / Interview Practice Questions after graduating from college.
A drunken cockroach is placed on the middle of a tile floor in a rectangular room that has N by M tiles. Searching for an aspirin, the bug wanders aimlessly from tile to tile throughout the room. Assuming that the cockroach may move from his present tile to any of the eight tiles surrounding him (unless he is against a wall) with equal probability, write a MODULARIZED program that stimulates the bug’s search for the aspirin.
Input N and M from the keyboard. The aspirin is randomly placed on a tile. Randomly generate integers from 1 to 8 to determine the cockroach’s next move. Use the following convention.
Please keep providing such valuable information.
MuchasGracias,
Irene Hynes
Commented:
All of these have their quirks and failings, and javascript has some traps for the unwary that even the C++ authors haven't managed to think of yet, but never have I felt that C++ would have been a better solution for what I was doing than any of the others in the domains I was coding for.
This is - of course - only my personal experience, and reflects on my skills and knowledge rather than that of anyone else - but as I get older, I believe that - as Occam did in the days of the transputer - C++ has become as much an 'academic' language as a development system. The enemy of robust systems is complexity (study the three-mile island incident if you want to see what I mean here) and C++ has become such a complex system now that I cannot forsee any time when the effort needed to learn to use the current release properly would ever be repaid (for me) by the resulting code quality or rewards.
This is a shame, because - as I said - I was the most enthusiastic adopter of C++ one could imagine when it first appeared, but - IMHO - it has lost its way...
View More