Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Good idea or gimmick: Go-style OO-programming in C++ ?

Reply
Thread Tools

Good idea or gimmick: Go-style OO-programming in C++ ?

 
 
Öö Tiib
Guest
Posts: n/a
 
      03-11-2013
On Monday, 11 March 2013 16:23:56 UTC+2, (E-Mail Removed) wrote:
> On Monday, March 11, 2013 12:44:48 AM UTC-5, Öö Tiib wrote:
> > On Monday, 11 March 2013 04:26:50 UTC+2, (E-Mail Removed) wrote:
> > > char* CstringGive ()

> >
> > Error! I see 'char*' my rules suggested against raw pointers.
> >
> > > {
> > > ::cmw::marshalling_integer slen(*this);
> > > ::std::unique_ptr<char[]> cstr(::new char[slen.value + 1]);

> >
> > You should not use smart pointers for dynamic arrays. Use std::vector
> > or std::string. Smart pointer does 'delete', not 'delete[]' and so
> > you result with undefined behavior.

>
> This page --
> http://en.cppreference.com/w/cpp/memory/unique_ptr
> -- says,
> "There are two versions of std::unique_ptr:
>
> 1) Manages the lifetime of a single object (e.g. allocated with new)
> 2) Manages the lifetime of a dynamically-allocated array of objects (e.g.allocated with new[])"


Ok, I stand corrected. Still I suggested to use std::vector
(or std::string) instead. Those have some immediately useful additional
data and member functions.

> > Some bytes here or there. I was suggesting that RAII is better
> > versus GC. Stefan Ram asked how to avoid leaks, I suggested
> > robust rules for applying RAII. I did not say that it is
> > cost-free in all situations.

>
> You also said,
> "Never dereference a pointer without comparing it with
> 'nullptr' first."
>
> Do you object to this line:
>
> ::cmw::marshalling_integer slen(*this);
>
> ?


No. 'this' is not pointer variable. It is keyword that resolves into
rvalue pointer that may never be 'nullptr'. It is not a reference
only because it was added into language before references.
See http://www.stroustrup.com/bs_faq2.html#this

When 'this' somehow is 'nullptr' then some undefined behavior is
already in effect.
 
Reply With Quote
 
 
 
 
woodbrian77@gmail.com
Guest
Posts: n/a
 
      03-11-2013
On Monday, March 11, 2013 3:44:07 PM UTC, Öö Tiib wrote:
> On Monday, 11 March 2013 16:23:56 UTC+2, (E-Mail Removed) wrote:
>
> Ok, I stand corrected. Still I suggested to use std::vector
>
> (or std::string) instead. Those have some immediately useful additional
>
> data and member functions.
>


I'm fine with vector and string for the most part.

I have another function called charStarGive that
also returns a char*. The sending side has to
embed a null into the stream in order for things
to work correctly. Here's one place I use it:

if(!cmwBuf.boolGive()){
throw failure(::std::string("Login failed: ").append(cmwBuf.charStarGive()));
}

If I change that to
... append(cmwBuf.stringGive()) ...

The executable is 120 bytes bigger. I don't know
which way is better since the way I'm doing it
requires an extra byte in the message.

Brian
http://webEbenezer.net
 
Reply With Quote
 
 
 
 
Seungbeom Kim
Guest
Posts: n/a
 
      03-11-2013
On 2013-03-09 15:49, Juha Nieminen wrote:
> Seungbeom Kim <(E-Mail Removed)> wrote:
>> On 2013-02-27 01:21, Juha Nieminen wrote:
>>> SG <(E-Mail Removed)> wrote:
>>>> For C++ I would write:
>>>
>>> I think it can be summarized as: "Never write 'new' in a function that's
>>> not the member function of a class that takes care of automatically
>>> handling that allocation."

>>
>> That's too narrow. I consider it okay to pass the 'new' expression
>> directly to a member function of a class that takes care of automatically
>> handling that allocation, e.g.:
>>
>> std::unique_ptr<X> px(new X(...));
>>
>> px.reset(new X(...));

>
> I have never needed to do anything like that. My rule of thumb has
> worked just fine.


I guess that the first example ("std::unique_ptr<X> px(new X(...));"),
at least, is the most typical way to use std::unique_ptr. If you've
never given a new expression to the constructor of std::unique_ptr,
I wonder what else you've been giving.

--
Seungbeom Kim
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      03-11-2013
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> On Monday, March 11, 2013 3:44:07 PM UTC, Öö Tiib wrote:
>> On Monday, 11 March 2013 16:23:56 UTC+2, (E-Mail Removed) wrote:
>>
>> Ok, I stand corrected. Still I suggested to use std::vector
>> (or std::string) instead. Those have some immediately useful additional
>> data and member functions.
>>

>
> I'm fine with vector and string for the most part.
>
> I have another function called charStarGive that
> also returns a char*. The sending side has to
> embed a null into the stream in order for things
> to work correctly. Here's one place I use it:
>
> if(!cmwBuf.boolGive()){


boolGive seems to be a strange name, shouldn't the member name have
meaning (like "isOK") rather than a type?

> throw failure(::std::string("Login failed: ").append(cmwBuf.charStarGive()));


Why do you qualify std?

> }
>
> If I change that to
> ... append(cmwBuf.stringGive()) ...
>
> The executable is 120 bytes bigger. I don't know
> which way is better since the way I'm doing it
> requires an extra byte in the message.


Do you work in a small embedded environment?

--
Ian Collins
 
Reply With Quote
 
woodbrian77@gmail.com
Guest
Posts: n/a
 
      03-12-2013
On Monday, March 11, 2013 10:26:35 PM UTC, Ian Collins wrote:
>
> boolGive seems to be a strange name, shouldn't the member name have
>
> meaning (like "isOK") rather than a type?
>


That function is basically de-serializing a bool from a
buffer. That class also has a function named stringGive.
I'm all for meaningful names, but don't know if isOK would
be better.

>
> Why do you qualify std?
>


To avoid surprises. That particular use is in
an executable so am less concerned about that
than if it were in a library. But someone could
do something like this in their code:

namespace abcdefg {
namespace std {


}
}

The above might be written by an incompetent
programmer or maybe it's done as an intentional
hack. However it happens, it's likely to cause
confusion. So I write it that way so there's no
ambiguity if the environment is somehow corrupted.


>
> Do you work in a small embedded environment?
>


Not according to my literal understanding of those
terms, but in a way yes.

I don't have a big budget to accomplish my task.
My task is to provide a quality code generation
service to the world from (at this time) one
location.

I've taken thousands of steps over the course of
years to make the code as efficient as I know how.
I've received a lot of help from people here and
on other newsgroups to this end. Not having to
pay for what I don't need is important to the work.
People are free to examine the code on my website
to decide for themselves how the work is going.


Brian
Ebenezer Enterprises - in G-d we trust.
http://webEbenezer.net
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      03-12-2013
On Monday, 11 March 2013 20:01:16 UTC+2, (E-Mail Removed) wrote:
> On Monday, March 11, 2013 3:44:07 PM UTC, Öö Tiib wrote:
> > Ok, I stand corrected. Still I suggested to use std::vector
> > (or std::string) instead. Those have some immediately useful additional
> > data and member functions.

>
> I'm fine with vector and string for the most part.
>
> I have another function called charStarGive that
> also returns a char*. The sending side has to
> embed a null into the stream in order for things
> to work correctly. Here's one place I use it:
>
> if(!cmwBuf.boolGive()){


Typically names like "isOk", "good" or "fine" are used for clarity.

> throw


Note that 'throw' is expensive keyword; one should not write code
that does throw hundreds of times per second. It is for exceptional
situations. Therefore put most weight into clarity and usefulness of
information that you throw and care less about efficiency of gathering
it.

failure(::std::string("Login failed: ").append(cmwBuf.charStarGive()));
> }
>
> If I change that to
> ... append(cmwBuf.stringGive()) ...
>
> The executable is 120 bytes bigger.


I always pick clarity of code:

failure("Login failed: " + cmwBuf.message());

Later I find places modifying what I can raise the overall speed of
application two times and other places where I can reduce its total
memory usage two times. It is easier to do it without breaking something
if the code and data structure are clear and robust.

> I don't know which way is better since the way I'm doing it requires an
> extra byte in the message.


Extra byte in message is important when the messages consume significant
part of overall memory consumption. In every application there are only
few things that do it. Those are the things worth *major* attention. Rest
do not matter.

When we target platform that has only few kilobytes of memory then every
byte is important but then we do not throw exceptions with fancy dynamic
strings attached. We return int on such platforms 'return LoginFailed;'
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      03-12-2013
On Tuesday, 12 March 2013 12:30:25 UTC+2, Andy Champ wrote:
> On 12/03/2013 04:21, Öö Tiib wrote:
> > Note that 'throw' is expensive keyword; one should not write code
> > that does throw hundreds of times per second. It is for exceptional
> > situations. Therefore put most weight into clarity and usefulness of
> > information that you throw and care less about efficiency of gathering
> > it.

>
> Is this still true?
> (A quick test on my machine shows I can do 10,000,000 throw-catch cycles
> in 23 seconds)


Good catch, Andy, confirmed!

My error: I have done my tests with bloody MS debugger attached. That
evil thing spammed nonsense like "First-chance exception at 0x7c812fd3
(kernel32.dll) in Trying.exe: Microsoft C++ exception: bool at memory
location 0x0012ff6b" into some trace channel of IDE and killed the
performance thousand times despite it was release version.

throw is still 300 times slower than just returning a value but not
300 000 times worse like I thought. Thanks!
 
Reply With Quote
 
woodbrian77@gmail.com
Guest
Posts: n/a
 
      03-12-2013
On Tuesday, March 12, 2013 4:21:17 AM UTC, Öö Tiib wrote:
> I always pick clarity of code:
>
>
>
> failure("Login failed: " + cmwBuf.message());
>


I tried this:

throw failure("Login failed: ") << cmwBuf.charStarGive();

but it was 200 bytes larger than the original:

throw failure(::std::string("Login failed: ").append(cmwBuf.charStarGive()));

.. I value clarity and brevity, but the longer form
may be needed in this case.

The following has to do with your cmwBuf.message() code.
The message, from my perspective, consists of a bool and
an optional string depending on the value of the bool.

Here's the original snippet:

if(!cmwBuf.boolGive()){
throw failure(::std::string("Login failed: ").append(cmwBuf.charStarGive()));
}


>
>
> Later I find places modifying what I can raise the overall speed of
>
> application two times and other places where I can reduce its total
>
> memory usage two times. It is easier to do it without breaking something
>
> if the code and data structure are clear and robust.
>


Here's a link to the program -
http://webEbenezer.net/misc/cmwAmbassador.cc
.. I think it's decent/clear code, but admit there
are areas that need work.

Brian
Ebenezer Enterprises - helping to rebuild America.
http://webEbenezer.net
 
Reply With Quote
 
Rui Maciel
Guest
Posts: n/a
 
      03-12-2013
Andy Champ wrote:

> Is this still true?
>
> (A quick test on my machine shows I can do 10,000,000 throw-catch cycles
> in 23 seconds)


Arguing against exception handling on the basis of an assumed performance
penalty is something which is only done if the point of using exceptions was
entirely missed. So, the answer to that question should be: who cares?


Rui Maciel
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      03-12-2013
On Tuesday, 12 March 2013 21:19:49 UTC+2, (E-Mail Removed) wrote:
> On Tuesday, March 12, 2013 4:21:17 AM UTC, Öö Tiib wrote:
> > I always pick clarity of code:
> >
> > failure("Login failed: " + cmwBuf.message());

>
> Here's the original snippet:
>
> if(!cmwBuf.boolGive()){
> throw failure(::std::string("Login failed: ").append(cmwBuf.charStarGive()));
> }


That charStarGive() looks dangerous because it provides non-const char
pointer into that private 'wrapper' member vector of your ReceiveBuffer.
What I meant was:

if(!cmwBuf.boolGive()){
throw failure("Login failed: " + cmwBuf.stringGive());
}

Other things that I randomly noticed:

The boolGive() that I saw was such:

bool boolGive () {
unsigned char boolRep;
Give(&boolRep, sizeof(boolRep));
return !!boolRep;
}

Inefficiency here matters if you transport lots of bools. Why not:

bool boolGive () {
return GiveOne() != 0;
}

It is likely more clear and robust too.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: App idea, Any idea on implementation? Matthew_WARREN@bnpparibas.com Python 0 02-05-2008 05:50 PM
App idea, Any idea on implementation? Dr Mephesto Python 3 02-05-2008 06:55 AM
VMWARE for simulation - good idea? Kevin MCSE 21 03-11-2005 01:40 PM
Nested conditional expressions ---- good idea/bad idea? nimmi_srivastav@yahoo.com C Programming 10 02-02-2005 10:51 PM
Re: Self-training good idea? Mark Smith MCSE 0 07-22-2003 04:51 PM



Advertisments