POV-Ray : Newsgroups : povray.off-topic : Undirected ramblings on C++ Server Time
28 Jul 2024 16:16:51 EDT (-0400)
  Undirected ramblings on C++ (Message 4 to 13 of 13)  
<<< Previous 3 Messages Goto Initial 10 Messages
From: Warp
Subject: Re: Undirected ramblings on C++
Date: 27 Feb 2014 18:27:37
Message: <530fc9e9@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
> For example, yesterday I wrote the following code:

>    auto iter = inputs.begin();

> VS happily accepted this declaration, and the code performed the way I 
> had intended it to. But GCC emitted some gabled message to the effect 
> that "iter" hasn't been declared or some such... Replacing the "auto" 
> keyword with an explicit type signature fixed the problem. But I didn't 
> think this was an especially new language feature...

Currently gcc will only accept C++11 code if you give the -std=c++11
command-line parameter to it (or -std=c++0x if you are using a slightly
older version of gcc). That's probably the problem you are having.
(I don't know when they will change gcc to accept C++11 by default.)

> In a similar vein, today I tried giving a variable the same name as a 
> class. VS didn't care; it compiled and ran my code just fine. GCC gave 
> me an utterly baffling error message which took me some considerable 
> while to figure out. Renaming the variable made it happy again.

I suppose I'd have to see an actual example to give an informed opinion.

> Not that VS is perfect, of course. Yesterday it gave me the dreaded 
> C2512 error: "no appropriate default constructor available".

Again, I'd have to see an actual example...

> As best as I can tell, this is somehow due to it being impossible to 
> auto-initialise reference fields? Not that any error message *told* me 
> this or anything like that...

In general, you can't make a reference point to a temporary.

> Speaking of which... I think I may be fundamentally misunderstanding 
> what references actually *do*. I had thought they were like pointers, 
> just that you can't make them null. But some sources claim they're like 
> pointers who's value can never change. So what, pray tell, does the 
> following do?

>    std::vectpr<int> foo;
>    std::vector<int> bar;
>    std::vector<int> & baz = foo;
>    baz = bar;

> I had imagined that the final line changes baz from pointing to foo and 
> to instead point to bar. But... if a reference can never change... then 
> what the hell am I changing?? O_O

"A reference can never change" means that you can't make it point to some
other object after initialization. It doesn't mean you can't change
whatever it's referencing.

In the above example "baz = bar;" is doing the exact same thing as
"foo = bar;" (because 'baz' is an "alias" to 'foo' via the fact that
it's a reference to it.) In other words, you are assigning the 'bar'
object to the 'foo' object by value (via the 'baz' reference.)

> It's times like these that make me want to step away from the keyboard 
> and go for a walk outside for a while. This stuff is just too 
> complicated to be left to mere mortals. It should only be touched by 
> people with a PhD in the official language spec.

I don't think it's that hard. A reference is basically an "alias" to
whatever it's referring to. Whatever you are doing to the reference
you are doing to the original.

(The "immutability" of the refence, if we can call it that, simply means
that you can't later make it an "alias" to some other object. It will
always be an "alias" to the object it was initialized with.)

-- 
                                                          - Warp


Post a reply to this message

From: Lars R 
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 03:23:20
Message: <53104778$1@news.povray.org>
On 02/27/2014 08:23 PM, Orchid Win7 v1 wrote:
> One of the most unexpected outcomes of my current employment is the
> amount of time I spend writing C++ code.
> 
> I remember I did spend a while dabbling with C++ years ago. (I think I
> even got Warp to install Haskell round about the same time...) But I
> never managed to write much beyond Hello World with it. But now, I find
> myself writing highly non-trivial code in C++. And that's kind of
> alarming, given I know nothing about C++...

I know that moment. I've also written a lot of C++ code until I realized
that I don't really _know_ the language.

I _really_ learned it when I had to give a C++ course to my colleagues.
I had (and still have) the expectation to myself to only teach what's
true. So I had to study a lot of C++'s hidden details, read the ISO
standard etc. to be sure that I tell always the truth in my course and
my pupils can rely on my words.

That reminds me on a movie quote (from "Contact"): "I had no idea!"


> For example, yesterday I wrote the following code:
> 
>   auto iter = inputs.begin();
> 
> VS happily accepted this declaration, and the code performed the way I
> had intended it to. But GCC emitted some gabled message to the effect
> that "iter" hasn't been declared or some such... Replacing the "auto"
> keyword with an explicit type signature fixed the problem. But I didn't
> think this was an especially new language feature...

You wrote C++11 code. gcc (at least up to 4.7) does C++11 code only when
requested explicitly (-std=c++11, or -std=c++0x in older compiler versions).

Don't know whether gcc 4.8 or 4.9 switch its default mode to C++11.


> Speaking of which... I think I may be fundamentally misunderstanding
> what references actually *do*. I had thought they were like pointers,

Wrong, totally wrong. Imagine C++ references just as "alias names" (to
existing objects).

Whether they might be implemented using pointers internally is not
relevant, because they just don't behave like pointers (or references in
Java) at all.

They are alias names. Nothing more.

>   std::vectpr<int> foo;
>   std::vector<int> bar;
>   std::vector<int> & baz = foo;
>   baz = bar;
>
> I had imagined that the final line changes baz from pointing to foo and
> to instead point to bar. But... if a reference can never change... then
> what the hell am I changing?? O_O

Hence "baz" is just an alias for "foo", you change "foo" if you change
"baz". That's easy, isn't it? :-)

Lars R.


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 03:28:31
Message: <531048af$1@news.povray.org>
>> In a similar vein, today I tried giving a variable the same name as a
>> class. VS didn't care; it compiled and ran my code just fine. GCC gave
>> me an utterly baffling error message which took me some considerable
>> while to figure out. Renaming the variable made it happy again.
>
> I suppose I'd have to see an actual example to give an informed opinion.

   struct Side
   {
     Pattern & Pattern;
     Pattern::iterator Iterator;
   }

The error message was something like "cannot change meaning of 'class 
Pattern' to 'Pattern'" or something equally cryptic. Renaming the first 
field fixed the problem.

>> Not that VS is perfect, of course. Yesterday it gave me the dreaded
>> C2512 error: "no appropriate default constructor available".
>
> Again, I'd have to see an actual example...

   struct Side
   {
     Pattern & Pattern;
     Pattern::iterator & Iterator;
   }

   struct State
   {
     Side & LeftSide;
     Side & RightSide;
     std::stringstream Buffer;
     bool Success;
   }

Every single line that declares a State variable gives me C2512. As you 
can see, I clearly *have not* defined any constructors, so that isn't 
the reason for a default constructor not existing.

>> Speaking of which... I think I may be fundamentally misunderstanding
>> what references actually *do*. I had thought they were like pointers,
>> just that you can't make them null. But some sources claim they're like
>> pointers who's value can never change. So what, pray tell, does the
>> following do?
>
>>     std::vectpr<int>  foo;
>>     std::vector<int>  bar;
>>     std::vector<int>  &  baz = foo;
>>     baz = bar;
>
>> I had imagined that the final line changes baz from pointing to foo and
>> to instead point to bar. But... if a reference can never change... then
>> what the hell am I changing?? O_O
>
> "A reference can never change" means that you can't make it point to some
> other object after initialization. It doesn't mean you can't change
> whatever it's referencing.
>
> In the above example "baz = bar;" is doing the exact same thing as
> "foo = bar;" (because 'baz' is an "alias" to 'foo' via the fact that
> it's a reference to it.) In other words, you are assigning the 'bar'
> object to the 'foo' object by value (via the 'baz' reference.)

So what you're saying is, a reference is a pointer where you can't ever 
change the *address* it points to, but you can change what's *at* that 
address?

Does that also mean that assigning one vector to another actually 
*copies* the entire vector? As in, a deep copy??

>> It's times like these that make me want to step away from the keyboard
>> and go for a walk outside for a while. This stuff is just too
>> complicated to be left to mere mortals. It should only be touched by
>> people with a PhD in the official language spec.
>
> I don't think it's that hard. A reference is basically an "alias" to
> whatever it's referring to. Whatever you are doing to the reference
> you are doing to the original.

I didn't mean references specifically. I just meant the entire language. 
Nobody would try to claim that C++ is small or simple or free of 
surprises. For example,

    struct Side
    {
      Pattern & ThePattern;
      Side(Pattern p) : ThePattern(p) {}
    }

Guess what? This segfaults when I run it. *You* probably see the problem 
immediately, but it took me 24 hours to figure out that there's a single 
missing character there...

Today it's references. Last time it was

   catch (std::exception e)
   {
     std::cout << e.what();
   }

which *always* says std::exception, even if that wasn't the exception 
thrown. The time before that, it was a memory leak due to an (empty) 
destructor not being virtual. There's so many buts and gotchas. And 
they're not the sort of thing where your program gives you the wrong 
answer; they're the sort of thing where you have a native crash and 
you're left utterly bewildered as to how the *hell* to discover what the 
problem was...


Post a reply to this message

From: Le Forgeron
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 05:20:53
Message: <53106305$1@news.povray.org>
Le 28/02/2014 09:28, Orchid Win7 v1 a écrit :

>>> Not that VS is perfect, of course. Yesterday it gave me the dreaded
>>> C2512 error: "no appropriate default constructor available".
>>
>> Again, I'd have to see an actual example...
> 
>   struct Side
>   {
>     Pattern & Pattern;
>     Pattern::iterator & Iterator;
>   }
> 
>   struct State
>   {
>     Side & LeftSide;
>     Side & RightSide;
>     std::stringstream Buffer;
>     bool Success;
>   }
> 
> Every single line that declares a State variable gives me C2512. As you
> can see, I clearly *have not* defined any constructors, so that isn't
> the reason for a default constructor not existing.

But the compiler is unable to generate the default constructor (no
parameter) when some fields are references: they cannot be nullptr, and
they cannot be changed after the constructor, so what would be their
default value ?
By using reference as fields, you disabled the default implicit
constructor. It's your responsibility to now provides one, if you want it.



> I didn't mean references specifically. I just meant the entire language.
> Nobody would try to claim that C++ is small or simple or free of
> surprises. For example,
> 
>    struct Side
>    {
>      Pattern & ThePattern;
>      Side(Pattern p) : ThePattern(p) {}
>    }
> 
> Guess what? This segfaults when I run it. *You* probably see the problem
> immediately, but it took me 24 hours to figure out that there's a single
> missing character there...

two missing characters ? ;& ?
the ; after the last }.
the & in the constructor (Side(Pattern& p) ).

> 
> Today it's references. Last time it was
> 
>   catch (std::exception e)
>   {
>     std::cout << e.what();
>   }
> 
> which *always* says std::exception, even if that wasn't the exception
> thrown. The time before that, it was a memory leak due to an (empty)
> destructor not being virtual. There's so many buts and gotchas. And
> they're not the sort of thing where your program gives you the wrong
> answer; they're the sort of thing where you have a native crash and
> you're left utterly bewildered as to how the *hell* to discover what the
> problem was...

catch should use reference & const, to avoid copy constructor with
implicit upper-casting (that's the reason of the reference) and save
some time on exit of the block (that's the const).

catch(const std::exception & e)



-- 
Just because nobody complains does not mean all parachutes are perfect.


Post a reply to this message

From: Lars R 
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 06:54:23
Message: <531078ef$1@news.povray.org>
> I didn't mean references specifically. I just meant the entire language.
> Nobody would try to claim that C++ is small or simple or free of
> surprises. For example,
> 
>    struct Side
>    {
>      Pattern & ThePattern;
>      Side(Pattern p) : ThePattern(p) {}
>    }
> 
> Guess what? This segfaults when I run it. *You* probably see the problem
> immediately, but it took me 24 hours to figure out that there's a single
> missing character there...

Hence every compiler is able to emit a - more or less (depends on the
compiler you use) helpful - warning here.

So it is a good idea to compile always with a high warning level and you
should respect the emitted warnings.

> 
> Today it's references. Last time it was
> 
>   catch (std::exception e)
>   {
>     std::cout << e.what();
>   }

Even better: I wrote code like this:

   if(error)
   {
       std::runtime_error("XY went wrong");
   }

but no exception occured, because ... I forgot to _throw_ the exception. :-)

Lars R.


Post a reply to this message

From: Warp
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 09:16:52
Message: <53109a54@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
>    struct Side
>    {
>      Pattern & Pattern;
>      Pattern::iterator Iterator;
>    }

I think you are misunderstanding what C++ references are. They are *not*
like Java references.

While internally references might be pointers, you should stop thinking
about them as such. As I said in my previous post, references are
effectively "aliases". In other words, a name that's an alias to an
object.

References must always be initialized to something and they cannot be
later changed to be an alias to something else. You can't have "null
references", nor uninitialized references.

While it's possible to have a reference as a member of a struct/class,
it's seldom useful. (There *are* some cases where it can be useful, but
it tends to be rare.) The reference must always be initialized, and it
can never be changed again. The former means that if you have a reference
member you have to write a constructor that initializes it. The latter
means that the class becomes non-assignable.

You are clearly trying to use references to make something like a
list/tree node. References cannot really be used for that in a sensible
manner (because as said the node becomes non-assignable and you can't
have "null references".) Such nodes are usually done with pointers instead.

As you should be well aware, you shouldn't start messing with pointers
in C++ unless you know what you are doing.

Also references can be misused. C++ is not gargabe-collected. It's not
guaranteed that the object that the reference is pointing to will remain
for as long as the reference does. (For example returning a reference to
a local object is possible, but undefined behavior. Don't do things like
that. Your program will just crash.)

If you can, use one of the standard library data containers. Writing your
own dynamic data container is error-prone if you don't have enough C++
experience.

> Every single line that declares a State variable gives me C2512. As you 
> can see, I clearly *have not* defined any constructors, so that isn't 
> the reason for a default constructor not existing.

The compiler cannot create a constructor because it doesn't know what
the reference should be initialized with.

Your fundamental problem is that you are trying to use references for
something they aren't meant for.

> So what you're saying is, a reference is a pointer where you can't ever 
> change the *address* it points to, but you can change what's *at* that 
> address?

It may be like that inside, but you should really just think of it as an
"alias" of the thing it's referring to. Whatever you do to the reference
you are doing to the original object.

> Does that also mean that assigning one vector to another actually 
> *copies* the entire vector? As in, a deep copy??

Like all standard data containers, they are handled by value. Assigning
one container object to another makes a deep copy.

This is not Java.

> I didn't mean references specifically. I just meant the entire language. 
> Nobody would try to claim that C++ is small or simple or free of 
> surprises. For example,

>     struct Side
>     {
>       Pattern & ThePattern;
>       Side(Pattern p) : ThePattern(p) {}
>     }

You should understand what's happening here.

The constructor is taking an object *by value*, which means that inside
the constructor 'p' is a temporary object (which will disappear when
the constructor ends.) You are then making 'ThePattern' a reference to
said temporary value. Then the constructor ends and... 'ThePattern' refers
to a non-existeng object. Crash.

You seem to be programming this like it were Java. C++ isn't.

Try to stop using references or pointers if you can. If you can't, then
try to use the standard data containers. If you absolutely *must* make
your own dynamic data container... well, you are going to make errors.

Does 'ThePattern' need to point to some other object, or can it simply
contain a *copy* of that object? If it can contain a copy, then make it
a non-reference. Then 'p' will be simply copied to it, and everything will
be fine and dandy.

> Today it's references. Last time it was

>    catch (std::exception e)
>    {
>      std::cout << e.what();
>    }

> which *always* says std::exception, even if that wasn't the exception 
> thrown.

I don't understand where you are getting at.

> The time before that, it was a memory leak due to an (empty) 
> destructor not being virtual.

I think one of the major problems you are having is that you insist in
allocating things dynamically and having pointers to them (instead of
using eg. smart pointers or just using the standard data containers.)

I code in C++ almost every day as my payjob. I write thousands and thousands
of likes of C++ code every year. Do you know when was the last time I wrote
the keywords 'new' or 'delete'? I don't even remember. It must have been
years.

A surprising amount of problems can be solved without ever writing a
single 'new' or 'delete', or having dangerous raw pointers pointing to
stuff. Most things can be handled by value, and 99% of dynamic data
managing can be used by using purely the standard data containers.

-- 
                                                          - Warp


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 14:16:30
Message: <5310e08e@news.povray.org>
On 28/02/2014 02:16 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] devnull>  wrote:
>>     struct Side
>>     {
>>       Pattern&  Pattern;
>>       Pattern::iterator Iterator;
>>     }
>
> I think you are misunderstanding what C++ references are.

Perhaps.

Basically, last time I read a book on C++, it said to never use pointers 
and always use references. So that's what I did. (And it worked - 
eventually. It just wasn't particularly easy...)

> You are clearly trying to use references to make something like a
> list/tree node. References cannot really be used for that in a sensible
> manner (because as said the node becomes non-assignable and you can't
> have "null references".) Such nodes are usually done with pointers instead.

Let me explain what I was *actually* trying to do...

I'm using an iterator to keep track of where I am in a collection. 
("Pattern" is actually a trivial alias to std::vector.) But as soon as 
you value-copy a container, all the iterators suddenly stop being valid. 
Ergo, I have to somehow avoid copying the vector at any cost.

What I would *actually* like to do is just throw iterators around. 
However, for reasons beyond my comprehension, nobody thought to include 
an "is_at_end()" method in the standard iterators. So without access to 
the original container, it's impossible to know if you've reached the 
end. If it weren't for this annoying detail, I wouldn't need references 
at all!

...well, OK, maybe I would. Because the whole *point* of the code I'm 
writing is that you call some function, passing a bunch of iterators, 
and when that function returns, the iterators have moved. That's not 
going to work if you pass iterators by value. (And yet, when I started 
searching the Internet, everybody seemed to think having a pointer to an 
iterator is 100% guaranteed to be a bug...)

> As you should be well aware, you shouldn't start messing with pointers
> in C++ unless you know what you are doing.

In the one place where I had to do that, it made me really nervous...

>> Every single line that declares a State variable gives me C2512. As you
>> can see, I clearly *have not* defined any constructors, so that isn't
>> the reason for a default constructor not existing.
>
> The compiler cannot create a constructor because it doesn't know what
> the reference should be initialized with.

I figured that out eventually. But it would have been nice if the 
*compiler* could have told me that!

>> Does that also mean that assigning one vector to another actually
>> *copies* the entire vector? As in, a deep copy??
>
> Like all standard data containers, they are handled by value. Assigning
> one container object to another makes a deep copy.

I always find it slightly surprising when C++ actually does stuff for 
you automatically. Everything seems to manual most of the time...

>> I didn't mean references specifically. I just meant the entire language.
>> Nobody would try to claim that C++ is small or simple or free of
>> surprises. For example,
>
>>      struct Side
>>      {
>>        Pattern&  ThePattern;
>>        Side(Pattern p) : ThePattern(p) {}
>>      }
>
> You should understand what's happening here.
>
> The constructor is taking an object *by value*, which means that inside
> the constructor 'p' is a temporary object (which will disappear when
> the constructor ends.) You are then making 'ThePattern' a reference to
> said temporary value. Then the constructor ends and... 'ThePattern' refers
> to a non-existeng object. Crash.

Yeah. I figured that out eventually. Not, of course, that you can ask 
the IDE to trap a segfault and pop up the line of code it was trying to 
run when the crash happened. I had to laboriously step through the code 
line by line until I discovered the problem.

> You seem to be programming this like it were Java. C++ isn't.

It would be more accurate to say "like it were C#".

> Try to stop using references or pointers if you can.

It would certainly be simpler if I could find a way to do that...

> Does 'ThePattern' need to point to some other object, or can it simply
> contain a *copy* of that object?

As I say, copying it stops all the iterators working.

>> Today it's references. Last time it was
>
>>     catch (std::exception e)
>>     {
>>       std::cout<<  e.what();
>>     }
>
>> which *always* says std::exception, even if that wasn't the exception
>> thrown.
>
> I don't understand where you are getting at.

Apparently you have to say "std::exception & e", otherwise whatever the 
exception was gets type-cast to a plain std::exception. (In particular, 
I was throwing std::runtime_error with an explanatory message, and 
tearing my hair out trying to figure out why the hell I can't see the 
message in the debug logs...)

>> The time before that, it was a memory leak due to an (empty)
>> destructor not being virtual.
>
> I think one of the major problems you are having is that you insist in
> allocating things dynamically and having pointers to them (instead of
> using eg. smart pointers or just using the standard data containers.)

The memory leak was due to some code that does actual run-time 
polymorphism. As I understand it, it's impossible to do dynamic dispatch 
in C++ without pointers.

> I code in C++ almost every day as my payjob. I write thousands and thousands
> of likes of C++ code every year. Do you know when was the last time I wrote
> the keywords 'new' or 'delete'? I don't even remember. It must have been
> years.

The code I'm fiddling with today doesn't contain *any* dynamic 
allocation at all. I'm merely trying to use references to avoid copying 
stuff, to keep iterators valid, and to allow a function to alter 
variables in the caller (i.e., "out parameters").



As an amusing aside, the other day I got to read some code where a guy 
did the opposite of what you accuse me of: he wrote C# as if it was C++. 
It was ugly! I especially enjoyed how EVERY SINGLE CLASS had an explicit 
destructor like this:

   public class Foo
   {
     private Bar _bar1, _bar2, _bar3;

     ...

     public ~Foo()
     {
       // Set fields to NULL to let the garbage collector know that
       // the memory can be reclaimed.
       _bar1 = null;
       _bar2 = null;
       _bar3 = null;
     }

...um, yeah, I'm not sure you're understanding this whole "automatic 
garbage collection" idea. :-P If this destructor ever runs, then it is 
highly likely that the fields you're nulling out have *already* been 
garbage collected! In fact, ironically, by writing an explicit 
destructor, you're actually keeping the object alive *longer*!

(In C#, any object that has a destructor gets added to a special list, 
and the destructor gets run on the *next* GC sweep. So normal objects 
get collected in one sweep, objects with a destructor take two 
consecutive GC sweeps to reclaim. Oops!)

In short, this code does the *opposite* of what the comment claims. If I 
just saw the code, I'd be puzzled. But the comment displays a 
fundamental misunderstanding of how the language actually works...


Post a reply to this message

From: Warp
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 14:57:47
Message: <5310ea3b@news.povray.org>
Orchid Win7 v1 <voi### [at] devnull> wrote:
> Basically, last time I read a book on C++, it said to never use pointers 
> and always use references.

References aren't going to magically solve the problems that pointers
have.

> I'm using an iterator to keep track of where I am in a collection. 
> ("Pattern" is actually a trivial alias to std::vector.) But as soon as 
> you value-copy a container, all the iterators suddenly stop being valid. 
> Ergo, I have to somehow avoid copying the vector at any cost.

> What I would *actually* like to do is just throw iterators around. 
> However, for reasons beyond my comprehension, nobody thought to include 
> an "is_at_end()" method in the standard iterators. So without access to 
> the original container, it's impossible to know if you've reached the 
> end. If it weren't for this annoying detail, I wouldn't need references 
> at all!

I don't really understand what it is that you are trying to do, but it
sounds to me like you are trying to do it in a much more complicated
manner than it probably needs to.

If you have your elements in a vector, and you are only adding elements
to it, then try using indices instead of iterators/pointers.

> I always find it slightly surprising when C++ actually does stuff for 
> you automatically. Everything seems to manual most of the time...

Why is it surprising? That's the whole point for the existence of RAII.
(The name pretty much implies it.)

> Yeah. I figured that out eventually. Not, of course, that you can ask 
> the IDE to trap a segfault and pop up the line of code it was trying to 
> run when the crash happened. I had to laboriously step through the code 
> line by line until I discovered the problem.

There exist programs that can track the execution of your program and
notify you of such errors. (valgrind is one example in Linux, but there
are others for Windows. I don't know if there are any free ones.)

> > Does 'ThePattern' need to point to some other object, or can it simply
> > contain a *copy* of that object?

> As I say, copying it stops all the iterators working.

Why do you need iterators in the first place? Having iterators pointing
to a data container inside some object which gets passed around is not
only a very bad idea, it's highly confusing from a program design point
of view. It just sounds to me like you are making the program a lot more
complicated than it needs to be.

This isn't Haskell.

> >> Today it's references. Last time it was
> >
> >>     catch (std::exception e)
> >>     {
> >>       std::cout<<  e.what();
> >>     }
> >
> >> which *always* says std::exception, even if that wasn't the exception
> >> thrown.
> >
> > I don't understand where you are getting at.

> Apparently you have to say "std::exception & e", otherwise whatever the 
> exception was gets type-cast to a plain std::exception. (In particular, 
> I was throwing std::runtime_error with an explanatory message, and 
> tearing my hair out trying to figure out why the hell I can't see the 
> message in the debug logs...)

Well, if you are taking an object by value, you will get a value of
that particular type...

> The memory leak was due to some code that does actual run-time 
> polymorphism. As I understand it, it's impossible to do dynamic dispatch 
> in C++ without pointers.

You can use references as well in many cases. For example

  void foo(const MyClass& obj)
  {
      // If 'func()' is virtual and 'obj' is of a derived type, the derived
      // class implementation will be called:
      obj.func();
  }

> The code I'm fiddling with today doesn't contain *any* dynamic 
> allocation at all. I'm merely trying to use references to avoid copying 
> stuff, to keep iterators valid, and to allow a function to alter 
> variables in the caller (i.e., "out parameters").

It just sounds like you are implementing a kludge to get around the
problems of a needlessly complex design.

Iterators are effectively pointers. (In the case of std::vector, they
may well be *literally* pointers.) They have all the same problems as
pointers.

> As an amusing aside, the other day I got to read some code where a guy 
> did the opposite of what you accuse me of: he wrote C# as if it was C++. 
> It was ugly! I especially enjoyed how EVERY SINGLE CLASS had an explicit 
> destructor like this:

"As if it was C++" is a bit... off. I seldom write any destructors myself.
I don't need to.

-- 
                                                          - Warp


Post a reply to this message

From: Le Forgeron
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 15:25:52
Message: <5310f0d0$1@news.povray.org>
Le 28/02/2014 20:16, Orchid Win7 v1 nous fit lire :
> 
> What I would *actually* like to do is just throw iterators around.
> However, for reasons beyond my comprehension, nobody thought to include
> an "is_at_end()" method in the standard iterators.

For a container foo (of class Foo), the iterator (forward) is at end
when == foo.end() .

If you like for(auto k: foo), you would be better inspired with for(auto
& k: foo) (otherwise k is a copy of each element of foo.

The classical for() is : for( k = foo.begin(); k!= foo.end(); ++k)


Post a reply to this message

From: Le Forgeron
Subject: Re: Undirected ramblings on C++
Date: 28 Feb 2014 15:32:58
Message: <5310f27a$1@news.povray.org>
Le 28/02/2014 20:16, Orchid Win7 v1 nous fit lire :
> I'm using an iterator to keep track of where I am in a collection.
> ("Pattern" is actually a trivial alias to std::vector.) But as soon as
> you value-copy a container, all the iterators suddenly stop being valid.
> Ergo, I have to somehow avoid copying the vector at any cost.

If you have a vector, you can replace your iterator with an index. And
such index would remain valid even after a copy. (and access element via
the [] or at() ). Index starts at 0, and stop just before size().

About invalidation of iterator when value-copy is perform, it is not
always true.

A site for technical minded: http://en.cppreference.com/w/

A site with different approach: http://www.cplusplus.com/reference/

The second gives more details about invalidation of iterator by operations.


Post a reply to this message

<<< Previous 3 Messages Goto Initial 10 Messages

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.