http://groups.google.com/group/comp.lang.c++?hl=en
comp.lang.c++@googlegroups.com
Today's topics:
* Minimizing Dynamic Memory Allocation - 8 messages, 5 authors
http://groups.google.com/group/comp.lang.c++/t/c71ca35ca2b641b2?hl=en
* Doubts regarding const and temporaries.. - 2 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/bbe2b05f98b66310?hl=en
* comp language c++ - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/193b921aade69e4d?hl=en
* header file management practices - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/1fbdaadcf2c3575c?hl=en
* what is the best way to implement this problem? - 3 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/9688a6b11b41f339?hl=en
* "lifetime of temporary bound to reference..." - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/d9d9be987204ca40?hl=en
* Split a numeric value into bytes (char) - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/e34c86fa706a2b16?hl=en
* How to understand the C++ specification? - 3 messages, 2 authors
http://groups.google.com/group/comp.lang.c++/t/28b14a1308974070?hl=en
* A Convenient Exception Class - 3 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/297fe96f879fc326?hl=en
* Who is Marc Block? - 3 messages, 2 authors
http://groups.google.com/group/comp.lang.c++/t/cd174c617536f87b?hl=en
==============================================================================
TOPIC: Minimizing Dynamic Memory Allocation
http://groups.google.com/group/comp.lang.c++/t/c71ca35ca2b641b2?hl=en
==============================================================================
== 1 of 8 ==
Date: Mon, Jan 26 2009 11:50 pm
From: "Alf P. Steinbach"
* James Kanze:
> On Jan 24, 10:11 pm, "Alf P. Steinbach" <al...@start.no> wrote:
>> * ma740988:
>
> [...]
>>> and I'm having a hard time making it pass section 2.1.
>>> Section 2.1 reads
>
>>> -------
>>> Section 2.1 Minimizing Dynamic Memory Allocation
>>> Avoid the use of C's malloc and free.
>
>> Good advice for general C++, but of course there are no
>> absolutes, e.g., sometimes some library routine will require
>> you to 'malloc' some argument or 'free' some result.
>
> Then apply rule 0 (or what should be rule 0 in any reasonable
> coding guidelines): any other rule in the guideline can be
> violated if there is a justifiable reason for doing so. This
> reason must be documented in the code (comment, etc.), and
> approved by...
>
> They're called guidelines, and not laws, for a reason. In the
> end, if it passes code review, it's OK. Violating a guideline
> is a justifiable reason for the reviewers to reject it, but
> they aren't required to do so, if they're convinced that the
> violation was justified.
Code reviews are less often performed in the real world than you seem to think.
On the other hand, your idea of a rule 0 in any coding guideline is a very good one.
For if programming could be reduced to a simple set of mechanical rules it would
have been so reduced, long ago.
> Things that can be automatically checked (like use of
> malloc/free) may require some sort of special comment to turn
> the checking off in a particular case.
It seems you're envisioning some automated code-guideline-conformity checker.
Given the level of the OP's firm's new (proposed) guidelines that's an entirely
unreasonable supposition.
There's also the point that using such a checker would amount to have given up
on quality and instead focusing on enforcing unthinking rule conformity, and
that kind of conformity is not a good idea when what you need is intelligent,
creative staff.
>>> Instead use (sparingly) C++'s new and delete operators.
>
>> Also good advice, including that word 'sparingly'.
>
> For a definition of 'sparingly' which depends on the
> application. I can easily imagine numeric applications where no
> explicit use of new or delete is appropriate. And I've worked
> on server applications where almost everything was allocated
> dynamically, by necessity.
Which does not mean it's a good idea to pepper the code with 'new' calls.
Centralize that functionality.
> The real rule is more complex; it
> implies understanding what you are doing. Some simple rules can
> be applied, however:
>
> -- Never use dynamic allocation if the lifetime corresponds to
> a standard lifetime and the type and size are known at
> compile time.
std::scoped_ptr, bye bye. :-)
But I'm sure you're thinking of some given application domain familiar to you.
> -- If the object type doesn't require identity, and the
> lifetime does not correspond to a standard lifetime, copy it
> rather than using dynamic allocation, unless the profiler
> says otherwise.
>
>>> To avoid memory leaks, a clear understanding of resource
>>> acquisition (allocation and release) is important.
>
>> This is true.
>
>>> To avoid leaks, all classes should include a destructor
>>> that releases any memory allocated by the class' constructor.
>
>> This is just dumb advice.
>
> And it contradicts the advice immediately above: "have a clear
> understanding of resource acquisition".
>
>> Use types that manage their own memory.
>
> Which is exactly what the "advice" you just called dumb said.
Nope.
The "advice" in the proposed guidelines was to define a destructor in every
class. That's dumb on its own, as opposed to using resource-specific management
wrappers such as smart pointers and standard library container classes. And it's
even more dumb, downright catastrophic advice, when the author of the guidelines
isn't familiar with rule of 3 and forgets to mention it here.
The opposite of that approach is to use types that manage their own memory,
i.e., the opposite of mindless duplication and continuous re-invention of
resource management is to centralize it.
> There are two (and I think only two) cases where dynamic
> allocation is appropriate: the lifetime of the object doesn't
> correspond to a standard lifetime, or the size or type aren't
> known at compile time. In the second case, having a type which
> manages its own memory, and frees it in the destructor, is
> definitely the prefered solution. In the first case (by far the
> most prevalent in my applications), it really doesn't mean
> anything.
>
>> Use smart pointers.
>
> Whatever? Why does making the managing class look like a
> pointer change anything?
Making the managing class look like a pointer does change a few things, mainly
because of the language's operator-> support, but that change has nothing to do
with what was discussed.
> (There are cases where smart pointers
> are appropriate, but they don't solve all problems.)
Right, ANY LANGUAGE FEATURE OR TECHNIQUE is appropriate in some cases and
inappropriate in some other cases.
>>> To ensure that destructors are called, class constructors
>>> should be declared
>
>>> foo::foo ( a, b ) : a ( ... ), b ( ... ) { .... }
>
>>> and not
>
>>> foo::foo ( a, b ) { a = ...; b = ...; ... }
>
>>> because failure in the constructor after initialization of b
>>> will call the destructors for a and b in the first
>>> definition, but not in the second; thus in the second there
>>> is a potential memory leak.
>
>> This is incorrect.
>
>> However, it's generally a good idea to use initializer lists
>> rather than assignments.
>
>> See the FAQ.
>
> See also the response by Kai-Uwe. Just using initializer lists
> can make things worse.
It seems somebody has argued that "just using initializer lists" will correct
"things", presumably some problem.
But why are you remarking on that to me?
> A good general rule is to require any single class to be
> responsible for at most one resource. If a class needs several,
> it should spawn the management of each off into a separate base
> class or member. (There are times when this simplifies life
> even when the derived class only needs a single resource. See
> the g++ implementation of std::vector, for example.)
As a general rule I agree with that. Good advice.
>>> Finally, always set a 'new_handler' using the built-in
>>> function set_new_handler.
>
>> This is good advice.
>
>>> The default new_handler terminates the program when it
>>> cannot satisfy a memory request.
>
>> This is incorrect.
>
>>> Program termination at a critical time may be disastrous.
>
>> And this is just dumb.
>
> More to the point, it doesn't mean anything. And it's not
> implementable, at least not reasonably. If the OS crashes, for
> example, the program will terminate, or it may terminate because
> of a hardware failure. The total system must be so designed
> that this isn't "disastrous" (i.e. it doesn't result in a loss
> of lives or destruction of property).
>
>> The reason you should set a new_handler is in order to
>> override the default exception throwing behavior and instead
>> let it terminate the program.
>
>> Because that's about the only sane way to deal with memory
>> exhaustion.
>
> *That* depends largely on the application. In many cases,
> you're right, but certainly not all, and there are applications
> which can (and must) recover correctly to insufficient memory.
> (It's tricky to get right, of course, since you also have to
> protect against things like stack overflow and buggy systems
> which tell you you've got memory when you haven't.)
Hm, I'd like to see any application that, from a modern point of view, can deal
safely with a std::bad_alloc other than by terminating.
However, if you look up old clc++m threads you'll perhaps find the long one
where I argued with Dave Abrahams that one reasonable approach, for some
applications, is to use "hard" exceptions in order to clean up upwards in the
call stack before terminating (the problem being that C++ lacks support for
"hard" exceptions, so that the scheme would have to rely on convention, which is
always brittle).
E.g. it might be possible to save an open document to disk using only finite
pre-allocated resources.
But still I think the only sane way to deal with memory exhaustion is to
terminate, whether it happens more or less directly at the detection point or
via some "hard" exception.
Then it may perhaps be possible to do a "bird of Phoenix" thing, as e.g. the
Windows Explorer shell often does, or perhaps just a reboot. Or one might have
three machines running and voting, as in the space shuttle. Or whatever, but
continuing on when memory has been exhausted is, IMHO, simply a Very Bad Idea.
Cheers, :-)
- Alf
== 2 of 8 ==
Date: Tues, Jan 27 2009 1:44 am
From: Bart van Ingen Schenau
On Jan 26, 4:26 pm, p...@lib.hu wrote:
> And you miss the separation of responsibilities.
> We have RAII/RIID/manager/etc classes -- that have responsibility to
> manage a single resource. Examples: auto_ptr, string, vector, CFile,
> CSingleLock, shared_ptr. They normally reside in libraries ready to
> use. Ocasinally there is some some really new resource to cover, but
> it is more like exceptional.
No, I don't miss tthe separation of responsibilities. But I try to
write my coding standards in such a way that they can be applied
equally to both the common, non-resource owning, user classes and the
more exceptional resource manager classes.
Although every coding standard I know has a clause that you may break
the rules is you have a sufficiently good reason, you still have to
explain yourself in a code review and might even have to get a formal
management sign-off on the deviation. That will be enough of a hassle
for some programmers that they will just not write their resource
managers in a RAII fashion.
For that reason I won't actively discourage the writing of
destructors, but instead encourage practices like separation of
responsibilities, re-use of existing components and creating classes
with RAII semantics.
Bart v Ingen Schenau
== 3 of 8 ==
Date: Tues, Jan 27 2009 2:00 am
From: James Kanze
On Jan 27, 8:50 am, "Alf P. Steinbach" <al...@start.no> wrote:
> * James Kanze:
> > On Jan 24, 10:11 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> >> * ma740988:
> > [...]
> >>> and I'm having a hard time making it pass section 2.1.
> >>> Section 2.1 reads
> >>> -------
> >>> Section 2.1 Minimizing Dynamic Memory Allocation
> >>> Avoid the use of C's malloc and free.
> >> Good advice for general C++, but of course there are no
> >> absolutes, e.g., sometimes some library routine will require
> >> you to 'malloc' some argument or 'free' some result.
> > Then apply rule 0 (or what should be rule 0 in any reasonable
> > coding guidelines): any other rule in the guideline can be
> > violated if there is a justifiable reason for doing so. This
> > reason must be documented in the code (comment, etc.), and
> > approved by...
> > They're called guidelines, and not laws, for a reason. In the
> > end, if it passes code review, it's OK. Violating a guideline
> > is a justifiable reason for the reviewers to reject it, but
> > they aren't required to do so, if they're convinced that the
> > violation was justified.
> Code reviews are less often performed in the real world than
> you seem to think.
Probably. But without code reviews, there's no point in having
coding guidelines to begin with.
> On the other hand, your idea of a rule 0 in any coding
> guideline is a very good one.
It's interesting, because it is one of the first things I read
about coding guidelines.
> For if programming could be reduced to a simple set of
> mechanical rules it would have been so reduced, long ago.
Yep. And we'd be out of work (or at least paid a lot, lot
less):-).
> > Things that can be automatically checked (like use of
> > malloc/free) may require some sort of special comment to
> > turn the checking off in a particular case.
> It seems you're envisioning some automated
> code-guideline-conformity checker.
Yes and no. If some of the conformity checking is automated,
then you need some special handling for cases where rule 0 was
applied. (I've actually seen it done.)
> Given the level of the OP's firm's new (proposed) guidelines
> that's an entirely unreasonable supposition.
I have no idea what is going on in the OP's organization. But
I've seen some very badly organized places try to use automated
tools to impose bad rules. My point is just that if automated
checking is envisaged, then some provision for rule 0 must be
made.
> There's also the point that using such a checker would amount
> to have given up on quality and instead focusing on enforcing
> unthinking rule conformity, and that kind of conformity is not
> a good idea when what you need is intelligent, creative staff.
Some degree of rule conformity is a good idea, although it
certainly doesn't replace an intelligent, creative staff. And
it's always a good idea to automate what you can. What little
experience I've had with automated rule checking has been very
positive, but it was with a very good organization, which
understood the software development process very well. I've no
doubt that it can be seriously misused, however.
> >>> Instead use (sparingly) C++'s new and delete operators.
> >> Also good advice, including that word 'sparingly'.
> > For a definition of 'sparingly' which depends on the
> > application. I can easily imagine numeric applications
> > where no explicit use of new or delete is appropriate. And
> > I've worked on server applications where almost everything
> > was allocated dynamically, by necessity.
> Which does not mean it's a good idea to pepper the code with
> 'new' calls.
> Centralize that functionality.
Agreed. There should normally be few instances of new
expressions, even in applications where most objects are
dynamically allocated.
I'm sure that there are exceptions to even this, of course. My
real point is not that you are wrong, per se, but that the
definition of 'sparingly' will depend on the application.
> > The real rule is more complex; it implies understanding what
> > you are doing. Some simple rules can be applied, however:
> > -- Never use dynamic allocation if the lifetime corresponds to
> > a standard lifetime and the type and size are known at
> > compile time.
> std::scoped_ptr, bye bye. :-)
If the type and size are not known at compile time, it's
actually a very good solution. If the type and size are known,
and the lifetime corresponds to the scope, why would you
dynamically allocate?
> But I'm sure you're thinking of some given application domain
> familiar to you.
In this case, I think it's a general rule, applicable to all
applications. If the type and size are known at compile time,
and the lifetime corresponds to standard lifetime (i.e. a
lifetime defined by the language standard), then you should not
allocate dynamically.
> > -- If the object type doesn't require identity, and the
> > lifetime does not correspond to a standard lifetime, copy it
> > rather than using dynamic allocation, unless the profiler
> > says otherwise.
> >>> To avoid memory leaks, a clear understanding of resource
> >>> acquisition (allocation and release) is important.
> >> This is true.
> >>> To avoid leaks, all classes should include a destructor
> >>> that releases any memory allocated by the class' constructor.
> >> This is just dumb advice.
> > And it contradicts the advice immediately above: "have a clear
> > understanding of resource acquisition".
> >> Use types that manage their own memory.
> > Which is exactly what the "advice" you just called dumb said.
> Nope.
> The "advice" in the proposed guidelines was to define a
> destructor in every class.
Where did you see that? I don't see anything about "defining a
destructor". Just ensuring that the class has one (which all
classes do), and that it deletes any memory allocated in the
constructor. The obvious way of achieving that would be for all
of the pointers to memory allocated by the class be scoped_ptr.
> That's dumb on its own, as opposed to using resource-specific
> management wrappers such as smart pointers and standard
> library container classes. And it's even more dumb, downright
> catastrophic advice, when the author of the guidelines isn't
> familiar with rule of 3 and forgets to mention it here.
Hopefully, there would be other rules, concerning when and how
to support copy and assignment. Given the way this rule is
formulated, however, I can understand your doubts about this.
But they would be "other rules", and not necessarily part of
this one.
> The opposite of that approach is to use types that manage
> their own memory, i.e., the opposite of mindless duplication
> and continuous re-invention of resource management is to
> centralize it.
The necessity of requiring memory management to be pushed off
into a separate class doesn't seem correct to me. What's
important is to use standard and well understood idioms
(patterns). Thus, if you're using the compilation firewall, the
standard idiom is to provide a non-inline destructor which does
the delete---any attempt to use smart pointers is likely to get
you into problems with instantiating templates over an
incomplete type. (Such problems can be avoided by careful
choice of the pointer type, or by implementing one of your own.
But why bother?)
Again: there are three basic reasons to use dynamic allocation:
the size isn't known at compile time, the type isn't known at
compile time, and the lifetime of the object doesn't correspond
to a standard lifetime. The first is (usually, at least) best
handled by using a standard container, e.g. std::vector. The
second is (usually) best handled by a smart pointer (e.g.
boost::scoped_ptr), and the third needs explicit management---it
may be possible to design a smart pointer to handle it in
explicit cases, but not generally.
Beyond that, there are a few special idioms which require
dynamic allocation for other reasons---things like the
compilation firewall idiom (which is really a variant of not
knowing the exact type, or the details of the type, at least
when compiling client code) or the singleton pattern (but
usually, you're also trying to obtain a non-standard lifetime,
e.g. the destructor is never called---otherwise, you use a local
static). But they're just that, established and well known
patterns.
[...]
> > A good general rule is to require any single class to be
> > responsible for at most one resource. If a class needs several,
> > it should spawn the management of each off into a separate base
> > class or member. (There are times when this simplifies life
> > even when the derived class only needs a single resource. See
> > the g++ implementation of std::vector, for example.)
> As a general rule I agree with that. Good advice.
Finally:-).
I think our only difference (here, at least) is that you seem to
be suggesting that this class should usually look like a
pointer. Where as I find that the cases where it should look
like a pointer aren't all that frequent.
> >>> Finally, always set a 'new_handler' using the built-in
> >>> function set_new_handler.
> >> This is good advice.
> >>> The default new_handler terminates the program when it
> >>> cannot satisfy a memory request.
> >> This is incorrect.
> >>> Program termination at a critical time may be disastrous.
> >> And this is just dumb.
> > More to the point, it doesn't mean anything. And it's not
> > implementable, at least not reasonably. If the OS crashes,
> > for example, the program will terminate, or it may terminate
> > because of a hardware failure. The total system must be so
> > designed that this isn't "disastrous" (i.e. it doesn't
> > result in a loss of lives or destruction of property).
> >> The reason you should set a new_handler is in order to
> >> override the default exception throwing behavior and
> >> instead let it terminate the program.
> >> Because that's about the only sane way to deal with memory
> >> exhaustion.
> > *That* depends largely on the application. In many cases,
> > you're right, but certainly not all, and there are
> > applications which can (and must) recover correctly to
> > insufficient memory. (It's tricky to get right, of course,
> > since you also have to protect against things like stack
> > overflow and buggy systems which tell you you've got memory
> > when you haven't.)
> Hm, I'd like to see any application that, from a modern point
> of view, can deal safely with a std::bad_alloc other than by
> terminating.
A well written, robust LDAP server. There's absolutely no
reason why it should crash or otherwise terminate just because
some idiot client sends an impossibly complicated request. And
there's really no reason why it should artificially limit the
complexity of the request.
> However, if you look up old clc++m threads you'll perhaps find
> the long one where I argued with Dave Abrahams that one
> reasonable approach, for some applications, is to use "hard"
> exceptions in order to clean up upwards in the call stack
> before terminating (the problem being that C++ lacks support
> for "hard" exceptions, so that the scheme would have to rely
> on convention, which is always brittle).
> E.g. it might be possible to save an open document to disk
> using only finite pre-allocated resources.
> But still I think the only sane way to deal with memory
> exhaustion is to terminate, whether it happens more or less
> directly at the detection point or via some "hard" exception.
> Then it may perhaps be possible to do a "bird of Phoenix"
> thing, as e.g. the Windows Explorer shell often does, or
> perhaps just a reboot. Or one might have three machines
> running and voting, as in the space shuttle. Or whatever, but
> continuing on when memory has been exhausted is, IMHO, simply
> a Very Bad Idea.
What about a server whose requests can contain arbitrary
expressions (e.g. in ASN.1 or XML---both of which support
nesting)? The server parses the requests into a tree; since the
total size and the types of the individual nodes aren't known at
compile time, it must use dynamic allocation. So what happens
when you receive a request with literally billions of nodes? Do
you terminate the server? Do you artificially limit the number
of nodes so that you can't run out of memory? (But the limit
would have to be unreasonably small, since you don't want to
crash if you receive the requests from several different clients,
in different threads.) Or do you catch bad_alloc (and stack
overflow, which requires implementation specific code), free up
the already allocated nodes, and return an "insufficient
resources" error.
It's not a typical case, and most of the time, I agree with you.
But such cases do exist, and if the OP's organization is dealing
with one, then handling bad_alloc can make sense.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
== 4 of 8 ==
Date: Tues, Jan 27 2009 2:04 am
From: James Kanze
On Jan 26, 3:11 pm, Bart van Ingen Schenau
<Bart.van.Ingen.Sche...@ict.nl> wrote:
> On Jan 26, 2:07 pm, p...@lib.hu wrote:
> > >> - writing destructors is strictly discouraged
> > >Huh, that is new to me. Where did you get that from.
> > >> -- instead you shall use
> > >> RAII members and empty/autogenerated dtors
> > >Are you shure, you really are familliar with all implications of RAII?
> > I'm positive :)
> > Read James' recent post in this thread for details. (around
> > "A good general rule is to require any single class to be
> > responsible for at most one resource. ...")
And that class requires a user defined destructor. Writing
destructors is encouraged, not discouraged.
> > See also the "Single responsibility principle"
> It seems you seriously misunderstand what it means to manage a
> resource. If a class is responsible for managing a resource
> (a single resource preferably), then that class most
> definitely needs a destructor to clean-up after itself.
> The only classes that don't need a user-written destructor are
> those that don't need to do any cleanup when they are
> destroyed. This is typically because those classes don't
> manage any resources.
Or make any changes to program state. Most of my destructors
are concerned with roll back, not freeing resources.
> Depending on what you are writing, this could be a majority of
> the classes, but it still isn't enough to say that you should
> try to avoid writing destructors.
Note too that the compiler generated destructor is inline. I
tend to write a lot of destructors because of this as well.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
== 5 of 8 ==
Date: Tues, Jan 27 2009 2:18 am
From: James Kanze
On Jan 26, 4:26 pm, p...@lib.hu wrote:
> And you miss the separation of responsibilities.
> We have RAII/RIID/manager/etc classes -- that have
> responsibility to manage a single resource. Examples:
> auto_ptr, string, vector, CFile, CSingleLock, shared_ptr.
> They normally reside in libraries ready to use. Ocasinally
> there is some some really new resource to cover, but it is
> more like exceptional.
> Then there are the normal user classes this whole discussion
> is about. They, instead of attempting to manage resources
> directly shall use the classes mentioned before. As members,
> base classes, locally, etc. You do that, and need not write
> destructor (cctor, op= ) because cleanup is properly done.
> Most real-life problems come when a user class rather starts
> using raw pointers or raw resources, obviously messing up
> somewhere the first 5+ times. And only to eventually discover
> using a manager class.
> Care to point out what I miss? ;-)
The fact that library classes only handle general solutions, and
rarely cover the exact case you need. As time goes on, your
personal library will become more an more complete. For your
specific application domain and programming style.
Some things are well covered by the library: if the size isn't
known at compile time, std::vector, std::string et al. seem to
cover most of the cases. If the type isn't known, then you can
consider boost::scoped_ptr, but this still requires that the
pointed to type be completely defined in the header file, where
as a simple pointer doesn't, and if there is only one such
pointer, it really doesn't buy us that much. And in many cases,
clean up will be more complicated than simply calling delete.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
== 6 of 8 ==
Date: Tues, Jan 27 2009 2:29 am
From: "Alf P. Steinbach"
* James Kanze:
>
>>> -- Never use dynamic allocation if the lifetime corresponds to
>>> a standard lifetime and the type and size are known at
>>> compile time.
>
>> std::scoped_ptr, bye bye. :-)
>
> If the type and size are not known at compile time, it's
> actually a very good solution. If the type and size are known,
> and the lifetime corresponds to the scope, why would you
> dynamically allocate?
Sometimes just for convenience. But it may be that the class in question is
designed for dynamic allocation only. E.g., a window object class, and you're
doing the "main window" (however in this case a standard smart pointer is
usually not good enough).
[snip]
>>>>> To avoid leaks, all classes should include a destructor
>>>>> that releases any memory allocated by the class' constructor.
>
>>>> This is just dumb advice.
>
>>> And it contradicts the advice immediately above: "have a clear
>>> understanding of resource acquisition".
>
>>>> Use types that manage their own memory.
>
>>> Which is exactly what the "advice" you just called dumb said.
>
>> Nope.
>
>> The "advice" in the proposed guidelines was to define a
>> destructor in every class.
>
> Where did you see that?
Top of this quoted section. :-)
> I don't see anything about "defining a destructor".
The statement about "all classes should" is in a coding guideline.
[snip]
> I think our only difference (here, at least) is that you seem to
> be suggesting that this class should usually look like a
> pointer. Where as I find that the cases where it should look
> like a pointer aren't all that frequent.
Huh, where did you get that impression.
[snip]
> What about a server whose requests can contain arbitrary
> expressions (e.g. in ASN.1 or XML---both of which support
> nesting)? The server parses the requests into a tree; since the
> total size and the types of the individual nodes aren't known at
> compile time, it must use dynamic allocation. So what happens
> when you receive a request with literally billions of nodes? Do
> you terminate the server? Do you artificially limit the number
> of nodes so that you can't run out of memory? (But the limit
> would have to be unreasonably small, since you don't want to
> crash if you receive the requests from several different clients,
> in different threads.) Or do you catch bad_alloc (and stack
> overflow, which requires implementation specific code), free up
> the already allocated nodes, and return an "insufficient
> resources" error.
I haven't done that, and as I recall it's one of those things that can be
debated for years with no clear conclusion. E.g. the "jumping rabbit" (whatever
that is in French) maintained such a never-ending thread over in clc++m. But I
think I'd go for the solution of a sub-allocator with simple quota management.
After all, when it works well for disk space management on file servers, why not
for main memory for this? Disclaimer: until I've tried on this problem a large
number of times, and failed a large number of times with various aspects of it,
I don't have more than an overall gut-feeling "this should work" idea; e.g. I
can imagine e.g. Windows finding very nasty ways to undermine the scheme... :-)
Cheers,
- Alf
== 7 of 8 ==
Date: Tues, Jan 27 2009 2:38 am
From: Christof Donat
Hi,
>>> Because that's about the only sane way to deal with memory
>>> exhaustion.
>>
>> *That* depends largely on the application. [...]
>
> Hm, I'd like to see any application that, from a modern point of view, can
> deal safely with a std::bad_alloc other than by terminating.
I have not done things like that in C++ up to now, but I once wrote a Java
Application with a dynamically sized Cache that should possibly use all
available Heap untill it is needded somewhere else. Such an application
might have a use for catching std::bad_alloc in order to ask the Cache to
free some memory and try again.
Christof
== 8 of 8 ==
Date: Tues, Jan 27 2009 2:51 am
From: Michael DOUBEZ
pasa@lib.hu wrote:
>>> - writing destructors is strictly discouraged
>> Huh, that is new to me. Where did you get that from.
>>> -- instead you shall use
>>> RAII members and empty/autogenerated dtors
>> Are you shure, you really are familliar with all implications of RAII?
>
> I'm positive :)
> Read James' recent post in this thread for details. (around "A good
> general rule is to require any single class to be responsible for at
> most one resource. ...")
>
> See also the "Single responsibility principle"
Requiring that a class should be responsible with at most one resource
has nothing to do with the Single Responsability Principle (RSP).
The first is a sound practice to have an exception safe code: managing
multiple resource in a exception safe way tends to be tedious and error
prone. While RSP is a OO principle for enhancing reuse and refactoring
of code; it is related to separation of concern (i.e. obtain good
functional decomposition).
--
Michael
==============================================================================
TOPIC: Doubts regarding const and temporaries..
http://groups.google.com/group/comp.lang.c++/t/bbe2b05f98b66310?hl=en
==============================================================================
== 1 of 2 ==
Date: Tues, Jan 27 2009 12:28 am
From: James Kanze
On Jan 26, 3:45 pm, red floyd <no.spam.h...@example.com> wrote:
> doublemaster...@gmail.com wrote:
> > On Jan 26, 1:09 pm, DerTop...@web.de wrote:
> >>>> doublemaster...@gmail.com ha scritto:
> >>>>> in the case of example (1) compiler says that "invalid inialization of
> >>>>> non-const string& to "const char *"..
> >>>>> if "Hello" is the const char * type...then
> >>>>> How can we assign char * str = "Hello";
> >>> On Jan 25, 6:32 pm, Christian Hackl <ha...@sbox.tugraz.at> wrote:
> >>>> This is an inconsistency (a hack) supported by the
> >>>> language for reasons of backward compatibility. The
> >>>> actual type of the literal "Hello" is char const [6].
> >> On 25 Jan., 14:57, "doublemaster...@gmail.com"
>
> >> <doublemaster...@gmail.com> wrote:
> >>> Backward compatibility? for which feature??? Could you pls tell me??
> >> Backward compatibility to the C programming language, which
> >> Mr. Stroustrup chose a basis for C++ (hence the name). In
> >> his opinion it would prevent too much C code from being
> >> compilable under his C++ compiler if he had not allowed the
> >> hack of assigning string literals to non-const string char
> >> pointers.
> > :) Thanks..I think now i should start digging why it is
> > allowed in C?? huh!
> Because when Kernighan and Ritchie defined the language, there
> was no "const". As such, char *s = "some string"; was quite
> legal. When ANSI (and later ISO) standardized C, not breaking
> existing code was a major effort, and so they allowed that one
> implicit conversion between const and non-const.
Actually, the C committee chose a different solution: making the
type of a string literal char[], and not char const[]. They did
say, however, that any attempt to modify it was undefined
behavior (although K&R explicitly allowed it to be modified, and
guaranteed that each string literal was a separate instance).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
== 2 of 2 ==
Date: Tues, Jan 27 2009 12:39 am
From: James Kanze
On Jan 26, 3:38 pm, Diwa <shettydiwa...@gmail.com> wrote:
> On Jan 25, 8:32 am, Christian Hackl <ha...@sbox.tugraz.at> wrote:
> If I remember reading Stroustrup's book, it says that the
> temporary is not destroyed till the expresssion containing has
> finished executing. I don't what expression means.
Excuse me, but you don't know the meaning of "expression"? In
what way: a problem with English (and you'd know the equivalent
in your native language), or you know the general meaning, but
are unsure of the exact, formal meaning in C++.
> Maybe the line of code. For example,
> string copyOfStr = fun()
> OR
> some_func(fun())
> In both the above cases, maybe the temporary is not destroyed
> till the line is executed completely.
Not a line of code. Lines have no formal meaning in C++ (once
the preprocessor has finished). An expression is an expression;
a production in the grammar of C++. And the formal rules are
slightly more complicated than Stroustrup's informal
presentation. There are two cases when the temporary lives
longer than the expression: when the expression is used to
initialize an object (your first example above), the lifetime of
the temporary holding the results of the expression is extended
until the object is fully initialized, and if the expression is
used to initialize a reference, and results in the reference
being bound to a temporary, the lifetime of that temporary is
extended to match the lifetime of the reference.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
==============================================================================
TOPIC: comp language c++
http://groups.google.com/group/comp.lang.c++/t/193b921aade69e4d?hl=en
==============================================================================
== 1 of 1 ==
Date: Tues, Jan 27 2009 12:31 am
From: Rose flower
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Discussion about C++ language, library, standards.
(Moderated). Low activity,
Usenet. comp.lang.c++.
The object-oriented C++ language.
High activity, Usene
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
http://babylonia.50webs.com.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
==============================================================================
TOPIC: header file management practices
http://groups.google.com/group/comp.lang.c++/t/1fbdaadcf2c3575c?hl=en
==============================================================================
== 1 of 1 ==
Date: Tues, Jan 27 2009 12:41 am
From: James Kanze
On Jan 26, 7:00 pm, "Bo Persson" <b...@gmb.dk> wrote:
> ssylee wrote:
> > On Jan 25, 9:15 am, nick_keighley_nos...@hotmail.com wrote:
> >> On 25 Jan, 11:57, Juha Nieminen <nos...@thanks.invalid> wrote:
> >>> The header file would only be a convenience. It would not
> >>> change the visibility of the functions.
> >> I'd argue the header file is the better technique. If the
> >> prototype changes then you only have to change the header
> >> rather than seacrh all the source for the embedded
> >> declarations.
> > Thanks for all your replies. If a particular function is
> > only used once in another cpp file, and declared an extern
> > in the cpp file using the function, would it make a
> > difference anyway in terms of ease of managing the project?
> It would, the day you realize that the function can also be
> used in a third cpp file.
> Happens all the time! :-)
More generally, the usual practice is to include the header in
the file that defines the function as well. So the compiler can
control various incompatibilities (e.g. if you modify the return
type).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
==============================================================================
TOPIC: what is the best way to implement this problem?
http://groups.google.com/group/comp.lang.c++/t/9688a6b11b41f339?hl=en
==============================================================================
== 1 of 3 ==
Date: Tues, Jan 27 2009 12:44 am
From: abir
This question may not be very specific to C++ , rather than C++ is
used as a language to implement it.
I have a set of points (a vector of ) as input for a system, just like
blackboard drawing.
where the point is defined as
struct point{ int x,int y;};
my job is to create an animal (or a few) out of those points. i may
even fail to create an animal if it doesn't look like any which i
know.
animal is like
struct animal{
typedef std::vector<point>::const_iterator iterator;
//animal(const std::vector<point>& points)///1 complex constructor
virtual void show(){
for(iterator it = begin; it!= end;++it){
put_pixel(*it);
}
}
static std::vector<animal*> make_animals(const std::vector<point>&
p){///3
///complex algorithm.
}
protected:
animal(iterator begin,iterator end) : begin(begin), end(end){}//
<2 simple constructor
iterator begin; iterator end;
};
struct elephant : public animal{
std::pair<iterator,iterator> get_trunk()const{
return std::make_pair(trunk_b,trunk_e);
}
protected:
iterator trunk_b,trunk_e;
};
struct horse : public animal{
}
my problem is that, i can't construct the animal in the animal
constructor, as it is a complex process (marked as 1 in the code) and
outcome may be a single animal or multiple or even none.
like a set of point may create an elephant or a pig (when the
algorithm gets confused).
so i thought to have a simple constructor which decouples the
algorithm to construct the object from the constructor (marked as 2).
In this case almost all of the processing logic goes to make_animals
(marked as 3) even the logic specific to elephant (like setting trunk
etc) etc, which sometimes i feel like anti-pattern.
Is it a usual solution for this kind of problem, or a better
alternative is there?
a second problem is that as make_animals is complex logic & also may
need to store state from call to call, so i am delegating it to a
class called animal_creator (alternative static can also be used).
like
static std::vector<animal*> make_animals(const std::vector<point>&
p,context& ctx){
return ctx.animal_creator.create(p);
}
however as only animal_creator can create all those animals, i need to
access private data member for them, which means that for all of the
animal class i need to make animal_creator friend. which i am not
liking very much.
Looking for a better alternative
thanks
abir
== 2 of 3 ==
Date: Tues, Jan 27 2009 1:38 am
From: Matthias Buelow
abir wrote:
> my problem is that, i can't construct the animal in the animal
> constructor, as it is a complex process (marked as 1 in the code) and
> outcome may be a single animal or multiple or even none.
> like a set of point may create an elephant or a pig (when the
> algorithm gets confused).
Can't you find some common operations for all animals (like, some basic
animal-to-point construction) and put it in the base class, and then
implement the animal-specific stuff in derived classes?
== 3 of 3 ==
Date: Tues, Jan 27 2009 4:05 am
From: "Daniel T."
abir <abirbasak@gmail.com> wrote:
> This question may not be very specific to C++ , rather than C++ is
> used as a language to implement it.
> I have a set of points (a vector of ) as input for a system, just like
> blackboard drawing.
> where the point is defined as
> struct point{ int x,int y;};
>
> my job is to create an animal (or a few) out of those points. i may
> even fail to create an animal if it doesn't look like any which i
> know.
Your problem is a basic pattern matching problem. You have a set of
points and you have a sequence of points: the input pattern... and a
another container of sequences of points. It is your job to see how many
of the second container match the points in the first container. Each
sequence of points in the second container is associated with an animal.
Once you know which sequences from the second container match up, you
can create the correct animals.
==============================================================================
TOPIC: "lifetime of temporary bound to reference..."
http://groups.google.com/group/comp.lang.c++/t/d9d9be987204ca40?hl=en
==============================================================================
== 1 of 1 ==
Date: Tues, Jan 27 2009 12:53 am
From: James Kanze
On Jan 26, 7:25 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> Igor R. wrote:
> > Does the rule in the subj applies to the following:
First, very importantly, the rule in the subject doesn't exist.
Whether a temporary is bound to a reference has no effect on its
lifetime. The only time the lifetime of a temporary is extended
is if a reference is initialized with a rvalue. (The
difference, of course, is whether a temporary is bound to a
reference is a transitive relationship; whether a temporary was
initialized with an rvalue isn't.)
> > std::pair<int, int> getPair()
> > {
> > return std::pair<int, int>(1, 2);
> > }
> > int main()
> > {
> > // is this legal?
> > const std::pair<int, int> &p1 = getPair();
> Yes, this is legal. The temporary returned by 'getPair' will
> have the same lifetime as the 'p1' reference (i.e. until
> 'main' returns).
Formally, it might be a copy of the temporary (which is also a
temporary) which has its lifetime extended (but I think this
possibility will be removed from C++0x).
> > // and this?
> > std::pair<int, int> &p2 = getPair();
> No, this is not legal. A temporary can only be bound to a
> reference to const.
No! A reference can only be initialized with an rvalue if it is
const and non volatile. But it's quite possible to arrange for
a temporary to bind to a non-const reference (const_cast, member
functions, etc.).
This point is in some ways related to my initial comment, above:
in order to bind a temporary to a non-const reference, you must
somehow arrange for the expression to be an lvalue. And since
the initialization expression of the temporary is not an rvalue,
the lifetime of the temporary will NOT be extended.
This is probably best explained with a simple example:
struct S
{
S& me() { return *this ; }
} ;
S& rs = S().me() ;
The reference rs is clearly bound to a temporary, even though
the reference is non-const. On the other hand, the reference
was not initialized with an rvalue expression, so the lifetime
of the temporary will NOT be extended beyond the end of the full
expression. (Technically, the temporary object S() will be
destructed before the reference rs is initialized. In practice,
there's no way a conforming program can tell, however.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
==============================================================================
TOPIC: Split a numeric value into bytes (char)
http://groups.google.com/group/comp.lang.c++/t/e34c86fa706a2b16?hl=en
==============================================================================
== 1 of 1 ==
Date: Tues, Jan 27 2009 1:00 am
From: Barzo
On 21 Gen, 18:07, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
>
> To make it byte order insensitive and ignore any padding bits you
> could do:
>
> #include <stdio.h>
> #include <limits.h>
>
> template<class T>
> void asBytes(T t, unsigned char* bytes)
> {
> for(int i = 0; i != sizeof t; ++i)
> bytes[i] = static_cast<unsigned char>(t >> i * CHAR_BIT &
> 0xff);
> }
>
> template<class T>
> void fromBytes(unsigned char const* bytes, T* t)
> {
> *t = 0;
> for(int i = 0; i != sizeof t; ++i)
> *t |= bytes[i] << CHAR_BIT * i;
> }
>
>
> Obviously, the above two functions only work with integer types.
Hi..like always I need to go a step forward...
I have a char* = {0x11, 0x8E, 0xCD, 0x8D} and I have to transform it
into a float value 294571405.
I've read some old posts but with no luck!
The following post (http://groups.google.it/group/comp.lang.c++/
browse_frm/thread/22a97dda79ea08fb/6e4af8cd9c7b0db3) is exatcly what I
need...it gives some solutions that seems to be not portable..
Any suggestions?
Tnx,
Daniele.
==============================================================================
TOPIC: How to understand the C++ specification?
http://groups.google.com/group/comp.lang.c++/t/28b14a1308974070?hl=en
==============================================================================
== 1 of 3 ==
Date: Tues, Jan 27 2009 1:01 am
From: James Kanze
On Jan 26, 12:07 pm, "doublemaster...@gmail.com"
<doublemaster...@gmail.com> wrote:
> On Jan 26, 12:42 am, Nosophorus <Nosopho...@gmail.com> wrote:
> > The first C++ book I read was "Rescued By C++". I thought it
> > a fairly nice introductory C++ book. It is not as "profound"
> > as "Thinking In C++" (which you can get for free from web).
> > BUT, as a first contact with the language, it is nice.
> > I recommend "Rescued By C++" as an introduction and, then,
> > "Thinking In C++" as the next step. After those two books,
> > maybe, the reader is well suited to wonder through
> > Stroustrup's "The C++ Programming Language".
> Hmm..Actually i am confiratable with C++ and have 2 years of
> experience in C++. I have read some other advanced books like
> Effective C++ , more effective C++ , etc..I feel that C++
> standard i should be reading because it decides sytanx and
> semantix of the C++. But it uses tough notations, definations
> that i am finding little diff to understand!
The standard is written in a variant of English sometimes called
standardese. It's designed (or at least intended) to be
absolutely precise and unambiguous, even at the cost of
understandability. It doesn't always succeed with its intent,
but in all cases, precision and a lack of ambiguity have
precedence over readability.
Having said that: the major problem with readability I have is
finding what I'm looking for. Who'd think to look for "lifetime
of temporaries" in the section on "special member functions"?
And the definition of a POD struct refers to the definition of
an aggregate, which is in the section on initializers. Once
I've found it, however... The quality of the prose varies, but I
find most of it pretty readable... and not always as precise and
unambiguous as I'd like.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
== 2 of 3 ==
Date: Tues, Jan 27 2009 1:05 am
From: James Kanze
On Jan 26, 6:15 pm, Noah Roberts <n...@nowhere.com> wrote:
> doublemaster...@gmail.com wrote:
> > Is there any way i can understand C++ specifications? Every
> > time i read..i find it diff to understand..so i read more
> > books on C++ and come back..still the result is same..Are
> > there any links, refereces or documents which helps to
> > parse specification easily?? I really wanna understand
> > that..pls help me..
> I disagree with the assessment of others here, that you don't
> need to read the standard. The standard should be on
> everyone's desk. It is the only way to know what's going on
> with your code in many situations.
If that's true, then the code you're writing is too complicated,
and makes too much use of limit conditions. About the only time
I'll refer to the standard when writing code is for library
functions, and that's just because I don't have any other
documentation on line.
> What's funny is that most the people who say you don't need it
> also refer to it regularly to answer questions asked in this
> newsgroup.
That's because a lot of questions here concern things you
shouldn't be doing in production code anyway:-).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
== 3 of 3 ==
Date: Tues, Jan 27 2009 4:02 am
From: Pete Becker
On 2009-01-27 04:01:51 -0500, James Kanze <james.kanze@gmail.com> said:
>
> Having said that: the major problem with readability I have is
> finding what I'm looking for. Who'd think to look for "lifetime
> of temporaries" in the section on "special member functions"?
Someone who looked in the index? All but one of the entries under
"temporary" point to the two pages in the subsection entitled
"Temporary objects". Granted, there's no "lifetime of" subentry, but
it's not hard to find.
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)
==============================================================================
TOPIC: A Convenient Exception Class
http://groups.google.com/group/comp.lang.c++/t/297fe96f879fc326?hl=en
==============================================================================
== 1 of 3 ==
Date: Tues, Jan 27 2009 1:51 am
From: magnus.moraberg@gmail.com
Hi,
When I create a class, I normally give it an exception Class -
class MyClass
{
private:
MyClassExpection(): public runtime_error
{
public:
MyClassExpection(const string& what) :
runtime_error("Exception within MyClass: " + what)
{
}
};
};
I can then use this class as follows within MyClass scope -
stringstream failStringStream;
failStringStream << "The Step Id: " << (unsigned int)step << " is
invalid";
throw MyClassExpection(failStringStream.str());
But I was wondering if I could add another constructor to my exception
class as follows -
MyClassExpection(const stringstream& what) :
runtime_error("Exception within MyClass: " + stringstream.str
())
{
}
and then use it like this -
throw MyClassExpection( stringstream() << "The Step Id: " <<
(unsigned int)step << " is invalid" );
or the less clear -
throw MyClassExpection( stringstream("The Step Id: ") << (unsigned
int)step << " is invalid" );
but these give a compiler error -
no matching function for call to
'FS::MyClass::MyClassExpection::MyClassExpection
(std::basic_ostream<char, std::char_traits<char> >&)'
This does work -
stringstream failStringStream;
failStringStream << "The Step Id: " << (unsigned int)step << " is
invalid";
throw MyClassExpection(failStringStream);
why do I get this error?
are there any better solutions to the issue I'm trying to solve. That
is, the creation of a convenient exception object on one line.
Thanks,
Barry.
== 2 of 3 ==
Date: Tues, Jan 27 2009 4:08 am
From: alasham.said@gmail.com
Hello,
The following should work. Regards
#include <sstream>
#include <stdexcept>
class MyClassExpection : std::runtime_error {
public:
explicit MyClassExpection( const std::basic_ostream<char,
std::char_traits<char> >& what ) :
std::runtime_error( "Exception within MyClass: " +
static_cast<const std::stringstream&>( what ).str() )
{ }
};
int main()
{
unsigned int step = 0;
throw MyClassExpection( std::stringstream("The Step Id: ") << step
<< " is invalid" ) ;
}
== 3 of 3 ==
Date: Tues, Jan 27 2009 5:05 am
From: Vidar Hasfjord
On Jan 27, 9:51 am, magnus.morab...@gmail.com wrote:
> [...]
> But I was wondering if I could add another constructor to my exception
> class as follows -
>
> MyClassExpection(const stringstream& what) :
> runtime_error("Exception within MyClass: " + stringstream.str
> ())
> {
> }
>
> and then use it like this -
>
> throw MyClassExpection( stringstream() << "The Step Id: " <<
> (unsigned int)step << " is invalid" );
I don't think it is a good idea to mix this string formatting feature
with your exceptions. They are really separate concerns. For a
convenient general inline string builder, see:
http://groups.google.com/group/comp.lang.c++.moderated/msg/a400421feca71ea1
This thread also explains the problems you encounter.
Regards,
Vidar Hasfjord
==============================================================================
TOPIC: Who is Marc Block?
http://groups.google.com/group/comp.lang.c++/t/cd174c617536f87b?hl=en
==============================================================================
== 1 of 3 ==
Date: Tues, Jan 27 2009 4:11 am
From: Hajime
Hello,
Who is Marc Block?
Stroustrup's 'The C++ Programming Language' 3rd Ed. Appendix A starts
with his maxim:
"There is no worse danger for a teacher than to teach words instead of
things."
I had investigated a little, but I cannot find original text other
than Stroustrup.
Anyone knows original text? Or anyone knows Marc Block?
I'm a Japanese novel writer and going to quote the maxim to my piece.
Thanks.
== 2 of 3 ==
Date: Tues, Jan 27 2009 4:43 am
From: Michael DOUBEZ
Hajime wrote:
> Who is Marc Block?
> Stroustrup's 'The C++ Programming Language' 3rd Ed. Appendix A starts
> with his maxim:
> "There is no worse danger for a teacher than to teach words instead of
> things."
> I had investigated a little, but I cannot find original text other
> than Stroustrup.
> Anyone knows original text? Or anyone knows Marc Block?
> I'm a Japanese novel writer and going to quote the maxim to my piece.
Marc Block is a french historian. I guess you can find his bio in
english somewhere. I found this one:
http://www.answers.com/topic/marc-bloch
Perhaps is it a quote from his book "The Historian's Craft"
--
Michael
== 3 of 3 ==
Date: Tues, Jan 27 2009 5:21 am
From: Hajime
Michael DOUBEZ <michael.dou...@free.fr> wrote:
> Hajime wrote:
> > Who is Marc Block?
> > Stroustrup's 'The C++ Programming Language' 3rd Ed. Appendix A starts
> > with his maxim:
> > "There is no worse danger for a teacher than to teach words instead of
> > things."
> > I had investigated a little, but I cannot find original text other
> > than Stroustrup.
> > Anyone knows original text? Or anyone knows Marc Block?
> > I'm a Japanese novel writer and going to quote the maxim to my piece.
>
> Marc Block is a french historian. I guess you can find his bio in
> english somewhere. I found this one:http://www.answers.com/topic/marc-bloch
>
> Perhaps is it a quote from his book "The Historian's Craft"
Thanks, but I cannot found the maxim in the book:
http://books.google.com/books?id=YZdCcT_1Z8YC&dq=The+Historian's+Craft&printsec=frontcover&source=bn&hl=ja&sa=X&oi=book_result&resnum=5&ct=result
I had investigated about Marc Bloch by French language, but it seems
to me that no one quotes the maxim, at least within the range of
google.
==============================================================================
You received this message because you are subscribed to the Google Groups "comp.lang.c++"
group.
To post to this group, visit http://groups.google.com/group/comp.lang.c++?hl=en
To unsubscribe from this group, send email to comp.lang.c+++unsubscribe@googlegroups.com
To change the way you get mail from this group, visit:
http://groups.google.com/group/comp.lang.c++/subscribe?hl=en
To report abuse, send email explaining the problem to abuse@googlegroups.com
==============================================================================
Google Groups: http://groups.google.com/?hl=en
No comments:
Post a Comment