Thursday, June 25, 2015

Digest for comp.lang.c++@googlegroups.com - 25 updates in 5 topics

JiiPee <no@notvalid.com>: Jun 25 01:07AM +0100

On 23/06/2015 07:17, David Brown wrote:
> value, and it stops the compiler being able to warn you if you use it
> before putting in the real value (compilers can warn about the use of
> uninitialised variables in most cases).
 
class Vector
{
public:
Vector() : data(nullptr) {}
void allocate(int size) { if(data==nullptr) data = new int[size];
else....}
private:
int* data;
int size=0;
};
 
Here, isnt it a good idea to use nullptr initialization?
Also, there is a risk that due to human errors we would have a bug such
that we do not remember to assign any valid value to this pointer. Then
it has a random address and can possible crash the program. But if you
set it to NULL then at least we can debug and find where is the problem.
if its not null we cannot even find it when debugging... could be a very
difficult to find such a bug because this pointer tell the rest of the
code: "hey, I have a valid address to use" even though it does not....
 
Thats why it eliminates this kind of risk, right?
JiiPee <no@notvalid.com>: Jun 25 01:15AM +0100

On 23/06/2015 07:17, David Brown wrote:
> On 22/06/15 22:34, JiiPee wrote:
> So if you don't have anything sensible to put in your variable, don't
> put anything in it (or don't declare it at all until you need it).
 
many functions assume that nullptr means "uninitialized" or "not set".
Thats why I think a pointer is an exeption here. yes, for an integer
what you said holds:
 
int a; // if no sensible value, then dont initialize
int* p = nullptr; // just make sure functions checking uninitialize
condition know that pointer is not set
Rectangle rect1; // no need to initialize necessary
 
pointer is a different here than others , right? so, its good to
initialize pointers to null but not initialize other type of objects/vars?
JiiPee <no@notvalid.com>: Jun 25 01:16AM +0100

On 23/06/2015 07:35, Stefan Ram wrote:
> be a natural way to rewrite the function into a form where
> every variable is initialized with a natural value if it is
> known what that function is supposed to do.
 
but what if we are talking about class members which are pointer types?
So not about functions
Ian Collins <ian-news@hotmail.com>: Jun 25 12:19PM +1200

JiiPee wrote:
> Rectangle rect1; // no need to initialize necessary
 
> pointer is a different here than others , right? so, its good to
> initialize pointers to null but not initialize other type of objects/vars?
 
If the class manages whatever the pointer will be assigned to, then yes
it should be initialised otherwise the class destructor may try and
delete garbage.
 
--
Ian Collins
JiiPee <no@notvalid.com>: Jun 25 01:23AM +0100

> auto main() -> int {}
 
heh, nice little trick I did not think before.... :) this works! new
form of main
legalize+jeeves@mail.xmission.com (Richard): Jun 25 12:49AM

[Please do not mail me a copy of your followup]
 
no@notvalid.com spake the secret code
> int size=0;
>};
 
>Here, isnt it a good idea to use nullptr initialization?
 
Sort of. It's only a good idea because you're avoiding the other
advice for writing good C++ programs:
 
- don't write you own "vector", use std::vector.
- don't use raw pointers, use a smart pointer like std::unique_ptr or
std::shared_ptr
 
In other words, this is a contrived example for the above reasons and
isn't a useful example in which to discuss what is a good idea or not.
 
>Also, there is a risk that due to human errors we would have a bug such
>that we do not remember to assign any valid value to this pointer.
 
...which is why you shouldn't use raw pointers in the first place.
 
>Thats why it eliminates this kind of risk, right?
 
Using standard containers and smart pointers is the preferred way to
avoid the problems of raw pointers.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
legalize+jeeves@mail.xmission.com (Richard): Jun 25 12:50AM

[Please do not mail me a copy of your followup]
 
no@notvalid.com spake the secret code
 
>many functions assume that nullptr means "uninitialized" or "not set".
 
Again, it's better to use smart pointers instead of raw pointers and
this problem is easily avoided.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
legalize+jeeves@mail.xmission.com (Richard): Jun 25 12:51AM

[Please do not mail me a copy of your followup]
 
no@notvalid.com spake the secret code
>> auto main() -> int {}
 
>heh, nice little trick I did not think before.... :) this works! new
>form of main
 
Meh. Might as well just write
 
int main() {}
 
The use of auto and -> here feels gratuitous.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
JiiPee <no@notvalid.com>: Jun 25 01:53AM +0100

On 25/06/2015 01:19, Ian Collins wrote:
 
> If the class manages whatever the pointer will be assigned to, then
> yes it should be initialised otherwise the class destructor may try
> and delete garbage.
 
For me I would feel risky not to initialize that member.
 
But sure there are situations where to optimize the performance in a
function I would not initialize it especially if the function is small
and the pointer is easily seen there as a local variable.
woodbrian77@gmail.com: Jun 24 07:30PM -0700

On Wednesday, June 24, 2015 at 7:49:53 PM UTC-5, Richard wrote:
 
> - don't write you own "vector", use std::vector.
> - don't use raw pointers, use a smart pointer like std::unique_ptr or
> std::shared_ptr
 
I would say to use raw pointers and use unique_ptr sparingly.
I haven't found a need for shared_ptr to this day.
 
Brian
Ebenezer Enterprises - So far G-d has helped us.
http://webEbenezer.net
Ian Collins <ian-news@hotmail.com>: Jun 25 02:30PM +1200

David Brown wrote:
> manager) and interprets the error messages from the compiler. Debugging
> also works well enough, connecting to my embedded systems using openocd
> or other proxies and interfaces.
 
One benefit I find with my mix of clients and targets
(Solaris/Illumos/Linux and embedded ARM) with NetBeans is the IDE
generates and builds from makefiles. So I can build any (or all) of the
targets from the command line. This also helps when working with Visual
Studio which can use the makefiles for a makefile project. NetBeans
also supports connections to remote hosts, so I can build my
applications for all supported versions of Linux and Solaris without
having to change windows.
 
> is important to me to be able to have multiple copies of the IDE open at
> the same time, with different workspaces - Eclipse handles that without
> problem.
 
If you prefer (as I do) to have a single instance of the IDE open with
multiple workspaces, NetBeans is a good choice. I particularly like the
ability to associate code formatting with projects - very handy if you
have clients with different coding standards!
 
--
Ian Collins
legalize+jeeves@mail.xmission.com (Richard): Jun 25 02:40AM

[Please do not mail me a copy of your followup]
 
Ian Collins <ian-news@hotmail.com> spake the secret code
 
>One benefit I find with my mix of clients and targets
>(Solaris/Illumos/Linux and embedded ARM) with NetBeans is the IDE
>generates and builds from makefiles.
 
CMake can target all of those as well as Xcode and Visual Studio with
a superior experience than a plain Makefile. When using a makefile
based project in VS, it doesn't know about your source files and
locating files in the solution has to be done through File / Open
instead of the solution expolorer. When I initially came from a unix
environment I thought the solution explorer was kinda dumb, but now I
have come to find that I really do use it quite a bit and it assists
me in navigating to the various source files in my project.
 
I don't know how well Xcode gets along with a Makefile style project.
My experience is primarily with Xcode 3 and using it's builtin project
files (which CMake can generate without any problems).
 
>If you prefer (as I do) to have a single instance of the IDE open with
>multiple workspaces, NetBeans is a good choice.
 
With VS and CLion it's one instance of the IDE per workspace. I
*think* Xcode lets you only have a single workspace in a given
instance of Xcode and I can't remember if you can have multiple
instances running or not.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
David Brown <david.brown@hesbynett.no>: Jun 25 09:07AM +0200

On 25/06/15 02:07, JiiPee wrote:
> int size=0;
> };
 
> Here, isnt it a good idea to use nullptr initialization?
 
Yes, but what you are doing here is not fake initialisation - you are
actively setting the value, and relying on the fact that it is set.
It's a totally different situation. We have been talking about /fake/
initialisation, where you put in an initialiser value that will never be
used.
 
When you have a variable of some sort, you want it to be in a valid
state before use. If you don't currently have any possible valid state
for it, and your compiler can warn of uninitialised use, then the
general rule is don't set it to anything. Otherwise, a signalling
invalid state is a better choice.
 
(Here "valid state" does not just mean a value that satisfies the
constraints and invariants of the class - it means holding a value that
makes sense at that stage in the code.)
 
> if its not null we cannot even find it when debugging... could be a very
> difficult to find such a bug because this pointer tell the rest of the
> code: "hey, I have a valid address to use" even though it does not....
 
When considering whether or not to put a fake initial value in a
variable or object, there are a few things to consider:
 
1. Does it help prevent bugs in the first place, or help them get
spotted at compile-time with compiler warnings?
 
2. Does it make the code clearer and easier to understand and maintain?
 
3. Does it help make run-time bugs easily detected?
 
4. Does it make a /noticeable/ performance difference?
 
 
Compilers are quite good at spotting the use of uninitialised variables.
They can't do that if the variable has been initialised with fake data
- so they can't tell you that you have forgotten to put in the /real/
data. Fake data hides the problem, and turns an obvious compile-time
warning into an obscure run-time effect that will be hard to find.
 
Clarity of code is obviously a major priority in any decision.
 
If the potential bug can't be found compile-time, setting the variable
to a "safe default" can make debugging harder, not easier. Of course
details are going to vary, but your aim here is to cause a hard crash
quickly rather than have something that sort-of works. Using nullptr
for pointers is often useful on PC software, because dereferencing null
pointers can give an immediate crash. But if you have a double, you
might get better effects initialising to -1.2e87 than 0.0.
 
And for the Vector class you gave, you /might/ want a nullptr data to
signal that allocation should be done automatically. But you might also
want to have asserts in other methods, causing hard crashes and messages
if the class is accidentally used without being properly initialised (at
least during development!).
 
 
> Thats why it eliminates this kind of risk, right?
 
You don't /eliminate/ risks, you /reduce/ them.
David Brown <david.brown@hesbynett.no>: Jun 25 09:22AM +0200

On 25/06/15 04:30, Ian Collins wrote:
> also supports connections to remote hosts, so I can build my
> applications for all supported versions of Linux and Solaris without
> having to change windows.
 
Eclipse also creates makefiles, but I prefer to write them myself -
combined with gcc's dependency file options my makefiles automatically
deal with updating dependency files as needed. Eclipse's project
management does quite a good job, but my makefiles are better, and
noticeably faster on big projects. It also keeps my makefiles
completely independent of the IDE - sometimes I need to build from the
command line.
 
> multiple workspaces, NetBeans is a good choice. I particularly like the
> ability to associate code formatting with projects - very handy if you
> have clients with different coding standards!
 
Eclipse can also associate different formatting standards with different
projects.
 
I am not sure it makes any difference having multiple IDE instances with
different workspaces, or having one IDE instance with multiple
workspaces - the effect is much the same. (How windows users manage to
cope without virtual desktops here is beyond me. Maybe windows users
only ever work on one thing at a time?) Since I work with various
different embedded devices, it is not uncommon for me to have different
customised versions of Eclipse open at the same time - I might have a
Freescale Kinetis Eclipse open for the firmware development, and another
"plain" Eclipse open for Python code on the PC side.
 
I suspect that either Eclipse or NetBeans would be as suitable for much
of my work - I use Eclipse because I am used to it (partly because it is
the standard for microcontroller development tools, with Microchip and
Atmel being almost the only exceptions). I'd be happy to try out other
IDEs, such as NetBeans or CLion, if it looked like they would be
significantly better for me - but it doesn't sound like there would be
much difference.
"Öö Tiib" <ootiib@hot.ee>: Jun 25 04:04AM -0700

On Thursday, 25 June 2015 02:18:26 UTC+3, JiiPee wrote:
 
> > Would it still look simple then?
 
> 40 methods in a class ? :) maybe a bit too much... there should be only
> a few in a class normally?
 
10-15 member functions in class is quite livable but 40 is
smelly (too lot of responsibilities) and should be perhaps
split up.
 
However things are worse in some code bases. Longest
god class I have seen was 137 000 lines of C# all on its
own. One guy simply rewrote it (did reuse no line of it)
into several classes because it was hopelessly
unmaintainable. That took two months. Perhaps Noob
has something like that to port.
Rosario19 <Ros@invalid.invalid>: Jun 25 07:43AM +0200

On Tue, 23 Jun 2015 01:29:42 +0000 (UTC),
>whatever group I'm working in at the time.
 
>I've done:
>- 'using namespace fmeh;' at file scope
 
as someone said, namespace should be the name of file where there is
the function in cpu instructions... each function has to be identify
1-1 in .executables that call it, by its name and the file where it
is... as
this.dll.namefunctionOrNameOperatorWhathevarMaingligYouWhant
 
so the way each functions should be called in a file for minimize
space in the code vew would be in each file as:
 
#define printf namedll.printf
or
#define P namedll.printf
 
"Öö Tiib" <ootiib@hot.ee>: Jun 25 03:23AM -0700

On Wednesday, 24 June 2015 20:35:06 UTC+3, Lynn McGuire wrote:
> > own sin() and cos() functions defined.)
 
> I do not disagree. It is just with 650K lines of C++ code, it is difficult
> to add.
 
With somewhat larger codebase it took one day of one person
to get rid of any 'using namespace' in it. It was fast and skilled
person but even man-week is usually insignificant percent from
planned effort with such code-bases.
 
> Someday, we will remove the using and add the std:: all over
> the place, we have been actually doing so for all new code in
> the last ten years.
 
Why someday? Just do it right away when you have any name
clashes. Namespaces *are* meant as tool for avoiding name
clashes.
"Öö Tiib" <ootiib@hot.ee>: Jun 25 01:15AM -0700

On Tuesday, 23 June 2015 07:03:42 UTC+3, Stefan Ram wrote:
> ...
> > return result;
 
> Since C++14 »-> int« is not necessary anymore:
 
Yes, but that was meant for generic contexts where
we usually do not have separate declaration and
definition and may have otherwise to write things
like '->decltype(that+other)' or worse.
 
It feels bad idea to not write a known simple return
type (like 'int') of mundane function out explicitly.
Think about the lot of nausea caused by (and
fortunately deprecated by now) implicit 'int' of C.
gwowen <gwowen@gmail.com>: Jun 25 01:21AM -0700

On Wednesday, June 24, 2015 at 5:10:25 PM UTC+1, Mr Flibble wrote:
 
> Talk about being anal-retentive...
 
> > auto main() -> int
 
> int main()
 
Amen. Is this from some sort of competition to the write least-comprehensible and backward-compatible code possible?
 
What is the possible benefit of saying "please infer the return type (the answer is int, by the way)"?
"Öö Tiib" <ootiib@hot.ee>: Jun 25 01:31AM -0700

On Wednesday, 24 June 2015 19:10:25 UTC+3, Mr Flibble wrote:
 
> Talk about being anal-retentive...
 
> > auto main() -> int
 
> int main()
 
Alf's style makes sense for people who feel that return
value of function in C and C++ is visually in "wrong"
place. It is matter of taste.
 
Lot of language neutral programming tools also show
declarations in style of PASCAL:
 
function max(num1, num2: integer): integer
 
For me both styles are readable; I only dislike
inconsistency within code-base. So if team wants
to switch then someone has to refactor *all* function
declarations and definitions in code base.
"Öö Tiib" <ootiib@hot.ee>: Jun 25 02:24AM -0700

On Thursday, 25 June 2015 11:22:03 UTC+3, gwowen wrote:
 
> > int main()
 
> Amen. Is this from some sort of competition to the write least-comprehensible and backward-compatible code possible?
 
> What is the possible benefit of saying "please infer the return type (the answer is int, by the way)"?
 
It helps visually a bit to differentiate between procedures
and functions (function is noun prefixed with 'auto',
procedure is verb prefixed with 'void').
 
So instead of ...:
 
// procedure
void burn_down_harddrive( Harddrive& h );
// function
double cosine( Degrees angle );
 
... we can have:
 
// procedure
void burn_down_harddrive( Harddrive& h );
// function
auto cosine( Degrees angle ) -> double;

I see that it is bit unorthodox at first but
if to look at it then it is tolerable when
used consistently in whole code base.
gwowen <gwowen@gmail.com>: Jun 25 03:07AM -0700

On Thursday, June 25, 2015 at 10:24:25 AM UTC+1, Öö Tiib wrote:
 
> void burn_down_harddrive( Harddrive& h );
> // function
> auto cosine( Degrees angle ) -> double;
 
and what does
 
auto do_stuff( Degrees angle ) -> void;
 
denote?
 
void burn_down_harddrive(Harddrive&j);
double cosine( Degrees angle);
 
"void" means a procedure (or, get this, a function that doesn't return anything). "any other type" means a function that does return something, and I don't have to scan to the end of the argument list to see what.
 
> I see that it is bit unorthodox at first but
> if to look at it then it is tolerable when
> used consistently in whole code base.
 
Almost anything is tolerable. The question was, what's the advantage?
David Brown <david.brown@hesbynett.no>: Jun 25 12:13PM +0200

On 25/06/15 10:21, gwowen wrote:
> least-comprehensible and backward-compatible code possible?
 
> What is the possible benefit of saying "please infer the return type
> (the answer is int, by the way)"?
 
In cases like this, it's only advantage is if you prefer that style for
cosmetic reasons.
 
The whole point of this syntax was for more complex expressions,
especially for template functions, where the return type depends on the
parameter types - thus you can't express the return type until after the
parameters are written.
Paul <pepstein5@gmail.com>: Jun 25 03:03AM -0700

Checking if a linked list is circular is a standard problem. My attempted solution is below. Could anyone advise on a smart pointer approach using unique_ptr or shared_ptr? Also, please let me know if there are any problems with this approach. I know it leaks memory but I'm looking to a smart-pointer implementation to fix that.
 
Thanks a lot, Paul.
 
#include <cstdio>
 
struct Node
{
int data;
Node* next;
 
};
 
// A fast pointer and a slow pointer are both initiated at the head.
// Circular if the slow pointer is ever ahead of the fast pointer.
bool isCycle(Node* head)
{
Node* slowPointer = head;
Node* fastPointer = head;
 
while(fastPointer && fastPointer->next && fastPointer->next->next)
{
slowPointer = slowPointer->next;
fastPointer = fastPointer->next->next;
 
if(fastPointer == slowPointer || fastPointer->next == slowPointer)
return true;
}
 
return false;
}
 
// Test against the expected results.
void testCycle(Node* head, bool expected)
{
printf(isCycle(head) == expected ? "Results as expected\n" : "This test case failed\n");
}
 
// Set up tests for small numbers of nodes
void smallTests()
{
Node* emptyList = nullptr;
testCycle(emptyList, false);
 
Node* List1 = new Node;
Node* ListCircular2 = new Node;
Node* ListNonCircular2 = new Node;
Node* ListCircular3 = new Node;
Node* ListNonCircular3 = new Node;
 
List1->next = nullptr;
List1->data = 1;
testCycle(List1, false);
 
ListCircular2 = List1;
ListCircular2 -> next = ListCircular2;
testCycle(ListCircular2, true);
 
ListNonCircular2 = ListCircular2;
ListNonCircular2->next = new Node;
ListNonCircular2->next->data = 2;
ListNonCircular2->next->next = nullptr;
testCycle(ListNonCircular2, false);
 
ListNonCircular3 = ListNonCircular2;
ListNonCircular3->next->next = new Node;
ListNonCircular3->next->next->data = 3;
ListNonCircular3->next->next->next = nullptr;
testCycle(ListNonCircular3, false);
 
ListCircular3 = ListNonCircular3;
ListCircular3->next->next->next = ListCircular3;
testCycle(ListCircular3, true);
 
}
 
int main()
{
smallTests();
return 0;
}
"Öö Tiib" <ootiib@hot.ee>: Jun 25 02:56AM -0700

> in terms of copy assignment, i.e. the other way around, and it was ...
> unpleasant. The problems start manifesting themselves when the classes
> are inherited from.
 
When classes are inherited from then it is perhaps better not
to have public 'swap' or public copy constructions/assignments.
 
I typically move copy/move construction of base classes to protected
and assignments I delete. Otherwise it is too fragile in sense that
bad usages will compile and manifest themselves only runtime.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: