comp.lang.c++
http://groups.google.com/group/comp.lang.c++?hl=en
comp.lang.c++@googlegroups.com
Today's topics:
* subset - 11 messages, 8 authors
http://groups.google.com/group/comp.lang.c++/t/898bcce92c1b97fc?hl=en
* Boost - 1 messages, 1 author
http://groups.google.com/group/comp.lang.c++/t/81738d66827a11c8?hl=en
* show all subset of a set - 5 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/708873746ae8ae59?hl=en
* Return by reference - 8 messages, 5 authors
http://groups.google.com/group/comp.lang.c++/t/f6dd94c3223a1dbf?hl=en
==============================================================================
TOPIC: subset
http://groups.google.com/group/comp.lang.c++/t/898bcce92c1b97fc?hl=en
==============================================================================
== 1 of 11 ==
Date: Fri, Feb 7 2014 4:30 am
From: mary8shtr@gmail.com
Hi.I write this program.but i should write it, too recursive.and Could you help me in this case.
#include <iostream>
using namespace std;
int pow(int a,int b)
{
int p=1;
for(int i=0;i<b;i++)
p=p*a;
return p;
}
int main()
{
int testcase=0;
int n;
long long *a;
a=new long long[200];
cin>>testcase;
int i=0;
int d,b,c;
while(i<testcase)
{
cin>>n;
for(int j=0,k=1;j<n;j++,k++)
{
a[j]=k;
}
for(int p=0;p<=pow(2,n)-1;p++)
{
cout<<'{';
d=p;
for(int m=0;m<n;m++)
{
c=pow(2,n-1);
b=c&d;
if(b!=0)
cout<<a[m]<<' ';
d=d<<1;
}
cout<<'}';
cout<<endl;
}
cout<<endl;
i++;
}
return 0;
}
== 2 of 11 ==
Date: Fri, Feb 7 2014 11:04 am
From: Barry Schwarz
It would make your code a lot easier to read if
You indented consistently.
You doubled space between lines only to separate sections of your
functions.
You used the space bar more frequently.
Why does the definition of testcase contain initialization?
Why is a defined as a pointer and not as an array?
In the 'm' for loop, why do you re-evaluate c each iteration when its
value never changes?
What is the output supposed to represent?
If you google for recursion in C, you should get several hits that
show how to convert an iterative solution to a recursive one. If you
don't find an example for pow, look at the one for factorial.
On Fri, 7 Feb 2014 04:30:47 -0800 (PST), mary8shtr@gmail.com wrote:
>Hi.I write this program.but i should write it, too recursive.and Could you help me in this case.
>
>#include <iostream>
>using namespace std;
>int pow(int a,int b)
>{
> int p=1;
> for(int i=0;i<b;i++)
> p=p*a;
> return p;
>}
>int main()
>
>{
> int testcase=0;
>
> int n;
>
> long long *a;
>
> a=new long long[200];
>
> cin>>testcase;
>
> int i=0;
>
> int d,b,c;
>
> while(i<testcase)
> {
> cin>>n;
>
> for(int j=0,k=1;j<n;j++,k++)
> {
> a[j]=k;
> }
>
>
> for(int p=0;p<=pow(2,n)-1;p++)
> {
> cout<<'{';
>
> d=p;
> for(int m=0;m<n;m++)
> {
>
> c=pow(2,n-1);
>
> b=c&d;
>
> if(b!=0)
>
> cout<<a[m]<<' ';
>
> d=d<<1;
> }
>
> cout<<'}';
>
> cout<<endl;
> }
>
> cout<<endl;
>
> i++;
> }
> return 0;
> }
--
Remove del for email
== 3 of 11 ==
Date: Fri, Feb 7 2014 4:06 pm
From: woodbrian77@gmail.com
On Friday, February 7, 2014 1:04:40 PM UTC-6, Barry Schwarz wrote:
> It would make your code a lot easier to read if
>
>
> You indented consistently.
> You doubled space between lines only to separate sections of your
> functions.
>
> You used the space bar more frequently.
>
I'm with you for the first two, but I've seen
some who I think are good programmers not use
many spaces within a line of code, and I write
it that way sometimes also:
http://webEbenezer.net/misc/direct.cc
>
> If you google for recursion in C,
Watch out for Google.
Duckduckgo cares about your privacy:
https://Duckduckgo.com
http://donttrack.us
Brian
Ebenezer Enterprises
http://webEbenezer.net
== 4 of 11 ==
Date: Sat, Feb 8 2014 2:33 am
From: David Harmon
On Fri, 07 Feb 2014 11:04:40 -0800 in comp.lang.c++, Barry Schwarz
<schwarzb@dqel.com> wrote,
>Why does the definition of testcase contain initialization?
Because you should never define an uninitialized variable without a
really good reason!
The given code looks like:
int testcase=0;
cin>>testcase;
while(i<testcase)
Now, there are many problems you might pick with that code, but
anything caused by initializing testcase to a default value in case
the cin input fails is not among them. Would you rather that the
subsequent loop go running off to some undetermined possibly huge
number just because testcase was never given a value?
== 5 of 11 ==
Date: Sat, Feb 8 2014 2:43 am
From: ram@zedat.fu-berlin.de (Stefan Ram)
David Harmon <source@netcom.com> writes:
>The given code looks like:
> int testcase=0;
> cin>>testcase;
> while(i<testcase)
>Now, there are many problems you might pick with that code, but
>anything caused by initializing testcase to a default value in case
>the cin input fails is not among them. Would you rather that the
>subsequent loop go running off to some undetermined possibly huge
>number just because testcase was never given a value?
Yes, otherwise the real error (not checking the stream
state after reading) might remain hidden even longer!
== 6 of 11 ==
Date: Sat, Feb 8 2014 4:05 am
From: David Brown
On 08/02/14 11:33, David Harmon wrote:
> On Fri, 07 Feb 2014 11:04:40 -0800 in comp.lang.c++, Barry Schwarz
> <schwarzb@dqel.com> wrote,
>> Why does the definition of testcase contain initialization?
>
> Because you should never define an uninitialized variable without a
> really good reason!
>
> The given code looks like:
> int testcase=0;
> cin>>testcase;
> while(i<testcase)
>
> Now, there are many problems you might pick with that code, but
> anything caused by initializing testcase to a default value in case
> the cin input fails is not among them. Would you rather that the
> subsequent loop go running off to some undetermined possibly huge
> number just because testcase was never given a value?
>
You should never unnecessarily initialise a variable, because that stops
the compiler checking your code for you.
If you leave "int testcase;" uninitialised, and later use it without
first setting its value, then the compiler's warnings will tell you.
But if you've used "int testcase = 0;", then the compiler can't help you
spot that error.
== 7 of 11 ==
Date: Sat, Feb 8 2014 5:25 am
From: Victor Bazarov
On 2/8/2014 7:05 AM, David Brown wrote:
> On 08/02/14 11:33, David Harmon wrote:
>> On Fri, 07 Feb 2014 11:04:40 -0800 in comp.lang.c++, Barry Schwarz
>> <schwarzb@dqel.com> wrote,
>>> Why does the definition of testcase contain initialization?
>>
>> Because you should never define an uninitialized variable without a
>> really good reason!
>>
>> The given code looks like:
>> int testcase=0;
>> cin>>testcase;
>> while(i<testcase)
>>
>> Now, there are many problems you might pick with that code, but
>> anything caused by initializing testcase to a default value in case
>> the cin input fails is not among them. Would you rather that the
>> subsequent loop go running off to some undetermined possibly huge
>> number just because testcase was never given a value?
>>
>
> You should never unnecessarily initialise a variable, because that stops
> the compiler checking your code for you.
>
> If you leave "int testcase;" uninitialised, and later use it without
> first setting its value, then the compiler's warnings will tell you. But
> if you've used "int testcase = 0;", then the compiler can't help you
> spot that error.
Reliance on compiler warnings can only be done in conjunction with other
ways of ensuring correctness of the code. Code reviews and following
coding standards are other methods. However, in the end there is no
single action that would completely protect of making a mistake.
Besides, warnings are non-normative and therefore are not consistent
from compiler to compiler or even from one version of the same compiler
to another.
That said, a random value is worse than a known one. It can lead to
unpredictable behavior of the program. Repeatability, even if the
actions of the program are incorrect, helps tremendously in fixing the bugs.
V
--
I do not respond to top-posted replies, please don't ask
== 8 of 11 ==
Date: Sat, Feb 8 2014 5:43 am
From: ram@zedat.fu-berlin.de (Stefan Ram)
Victor Bazarov <v.bazarov@comcast.invalid> writes:
>That said, a random value is worse than a known one.
n3290 does not call it »random«:
»if no initialization is performed, an object with automatic
or dynamic storage duration has indeterminate value.«
== 9 of 11 ==
Date: Sat, Feb 8 2014 7:37 am
From: Öö Tiib
On Saturday, 8 February 2014 15:43:03 UTC+2, Stefan Ram wrote:
> Victor Bazarov <v.bazarov@comcast.invalid> writes:
> >That said, a random value is worse than a known one.
>
> n3290 does not call it »random«:
>
> »if no initialization is performed, an object with automatic
> or dynamic storage duration has indeterminate value.«
Victor's point still holds since random is just (more useful) subset
of indeterminate. So if random is worse than known then indeterminate
is even worse.
== 10 of 11 ==
Date: Sat, Feb 8 2014 8:02 am
From: ram@zedat.fu-berlin.de (Stefan Ram)
Öö Tiib <ootiib@hot.ee> writes:
>On Saturday, 8 February 2014 15:43:03 UTC+2, Stefan Ram wrote:
>>Victor Bazarov <v.bazarov@comcast.invalid> writes:
>>>That said, a random value is worse than a known one.
>>n3290 does not call it »random«:
>>»if no initialization is performed, an object with automatic
>>or dynamic storage duration has indeterminate value.«
>Victor's point still holds since random is just (more useful) subset
>of indeterminate.
When someone says: »x e A« (»x is an element of A.«), and
the specs say: »x e B«, and »A c B« (»A is a subset of B«),
then »x e A« does /not/ follow from the specs (from »x e B«).
(It would follow if instead »B c A« would be true.)
Hey, we're on topic again, as the subject says: »subset«!
== 11 of 11 ==
Date: Sat, Feb 8 2014 8:15 am
From: David Brown
On 08/02/14 14:25, Victor Bazarov wrote:
> On 2/8/2014 7:05 AM, David Brown wrote:
>> On 08/02/14 11:33, David Harmon wrote:
>>> On Fri, 07 Feb 2014 11:04:40 -0800 in comp.lang.c++, Barry Schwarz
>>> <schwarzb@dqel.com> wrote,
>>>> Why does the definition of testcase contain initialization?
>>>
>>> Because you should never define an uninitialized variable without a
>>> really good reason!
>>>
>>> The given code looks like:
>>> int testcase=0;
>>> cin>>testcase;
>>> while(i<testcase)
>>>
>>> Now, there are many problems you might pick with that code, but
>>> anything caused by initializing testcase to a default value in case
>>> the cin input fails is not among them. Would you rather that the
>>> subsequent loop go running off to some undetermined possibly huge
>>> number just because testcase was never given a value?
>>>
>>
>> You should never unnecessarily initialise a variable, because that stops
>> the compiler checking your code for you.
>>
>> If you leave "int testcase;" uninitialised, and later use it without
>> first setting its value, then the compiler's warnings will tell you. But
>> if you've used "int testcase = 0;", then the compiler can't help you
>> spot that error.
>
> Reliance on compiler warnings can only be done in conjunction with other
> ways of ensuring correctness of the code. Code reviews and following
> coding standards are other methods. However, in the end there is no
> single action that would completely protect of making a mistake.
> Besides, warnings are non-normative and therefore are not consistent
> from compiler to compiler or even from one version of the same compiler
> to another.
>
That's all true - compiler warnings are an aid to avoiding bugs, but
they certainly don't cover everything. However, appropriate use of
compiler warnings should be a normal part of your development
methodology. If you are using a compiler that does not have a
reasonable level of warnings, then it is a good idea to use an external
tool (a "lint" tool), or simply pass the same code though a compiler
that /is/ good at static error checking. Since gcc is a suitable
choice, and is free, there is no good excuse for not using it as a
minimum (llvm is an alternative).
The worst thing you can do is say that since your compiler is not
perfect at static error checking, you should ignore it!
> That said, a random value is worse than a known one. It can lead to
> unpredictable behavior of the program. Repeatability, even if the
> actions of the program are incorrect, helps tremendously in fixing the
> bugs.
>
In a case like this, the initial value is only ever used if there is a
bug in later code. Giving the variable an initial value hides the bug
from helpful tools, and it certainly does not remove the bug. It is a
far stretch to claim that it makes the bug less bad (by having a known
value rather than an indeterminate one) - the bug is there, and the
program will not work.
==============================================================================
TOPIC: Boost
http://groups.google.com/group/comp.lang.c++/t/81738d66827a11c8?hl=en
==============================================================================
== 1 of 1 ==
Date: Fri, Feb 7 2014 6:07 pm
From: woodbrian77@gmail.com
On Friday, February 7, 2014 4:31:23 AM UTC-6, Öö Tiib wrote:
> On Friday, 7 February 2014 00:33:30 UTC+2, woodb...@gmail.com wrote:
>
> > On Thursday, February 6, 2014 4:56:27 AM UTC-6, Öö Tiib wrote:
>
> > I have tests that compare with the serialization
> > library in Boost.
>
> Its usage is very narrow (being language- and version-specific).
> Basically clipboard operations (undo/redo/cut/paste) within single
> application and dumping objects into text or xml file or log for
> debugging/problem reporting/code generation purposes.
>
> For those things it is adequate; it does not matter if undo takes
> 25 or 50 milliseconds. CMW feels even more narrow in sense that
> it does not look like suitable for most of named use-cases.
>
CMW doesn't support JSON or text formats, but I
don't think it's difficult for application written
using CMW to work with an application written in
a language other than C++. I don't have examples
of that, but there aren't difficult technical
problems behind doing that.
>
> It is more likely that someone wanting to actually serialise
> something between applications/services using boost uses
> Boost.PropertyTree instead.
>
>
> > I haven't updated my site yet, but I'm updating
> > those tests using Boost 1.55. For the
> > vector<deque<double> > test, the Boost version is
> > over 2 times slower than the CMW version. The
> > Boost-based executable is over 3 times larger than
> > the CMW-based executable.
>
> Yes, but what use case it is that you compare?
>
It's a low-level test. Applications are made up
of low-level operations ... I'm open to other
ideas of what to test.
>
>
> You push that 'std::vector<std::deque<double> >' reflection?
> Typically it is implementation detail that may change between
> versions. It is likely that profiling shows in version 2.1 that
> 'std::valarray' trumps 'std::deque' but it can't be done since
> that would make CMW of 2.2 not compatible with 2.1.
From a protocol perspective deque and valarray are
the same. First we marshal the size of the container
and then the elements. So it should be possible to
make the change you mention without compatibility
problem.
> Telling
> that it is indexed collection of indexed collections of floating
> point values gives it more longevity and is neutral to
> programming language.
>
>
> If C++ reflection is major property for you then there is cereal.
> http://uscilab.github.io/cereal/index.html (has JSON/XML and
> various binary representations).
The following type is from that link:
struct SomeData
{
int32_t id;
std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;
template <class Archive>
void save( Archive & ar ) const
{
ar( data );
}
template <class Archive>
void load( Archive & ar )
{
static int32_t idGen = 0;
id = idGen++;
ar( data );
}
};
The load function looks funny to me. In order
for something to be loaded, it has to have been
saved. How is id being set in code that's not
shown and can it be coherent with the static in
the load function?
I agree with their requiring C++ 2011 or newer.
But Cereal looks similar to the serialization
library in Boost. Users have to maintain
serialization functions and the dependence on iostream.
> There are even attempts of
> making reflection libraries:
> https://bitbucket.org/dwilliamson/clreflect
>
>
>
> > I'm not sure Protocol Buffers is worth comparing
> > against. If someone is interested in seeing that,
> > they can do a little bit to make it happen. I'm
> > happy to turn over my side of the test so they
> > can do the comparison at their location also.
>
> I'm also not sure. Those seem to be on same market
> between small enough for using text-based protocols
> and big enough for using real binary formats (audio,
> graphics, database etc.). Protobuf lacks reflection
> and CMW lacks language neutrality.
I think Protobuf has some support for reflection.
I don't think support for other languages is hard
to reach. Assuming we stick with byte-level
marshalling, I don't think there are difficult
problems in making applications written with
CMW work with applications in another language.
Also assuming IEEE 754 floating point.
Switching to bit-level marshalling would make
it more work to support other languages so
probably we won't do that.
Brian
Ebenezer Enteprises - In G-d we trust.
http://webEbenezer.net
==============================================================================
TOPIC: show all subset of a set
http://groups.google.com/group/comp.lang.c++/t/708873746ae8ae59?hl=en
==============================================================================
== 1 of 5 ==
Date: Sat, Feb 8 2014 12:17 pm
From: Dale Fletcher
Öö Tiib wrote:
> On Thursday, 6 February 2014 18:13:54 UTC+2, mary...@gmail.com wrote:
>> allow me explain it with a example.
>>
>> n=3
>> { } 000 0
>> {1} 100 4
>> {2} 010 2
>> {3} 001 1
>> {1,2} 110 6
>> {1,3} 101 5
>> {2,3} 011 3
>> {1,2,3} 111 7
>
> Your illustration seems messed up. Usually we expect to
> see that:
> n=3
> set binary decimal
> { } 000 0
> {1} 001 1
> {2} 010 2
> {1,2} 011 3
> {3} 100 4
> {1,3} 101 5
> {2,3} 110 6
> {1,2,3} 111 7
>
> Lower sub-patterns repeat so it is simple to make it recursive.
> Also like we see the decimal is now linear so it is pointless to
> make it recursive. ;)
Good observation. Then there is a question of unmasking the bits.
== 2 of 5 ==
Date: Sun, Feb 9 2014 12:39 am
From: ram@zedat.fu-berlin.de (Stefan Ram)
Dale Fletcher <dflach@twees.au> writes:
>Good observation. Then there is a question of unmasking the bits.
Do we need vectors assuming that 64-bit integer arithmetic
is available? On one hand, some sets might have more than
64 elements. (In 1997, Harkstrøm et al. reported a set with
more than 3000 elements!) On the other hand, printing all
subsets from a set with more than 64 elements might take
such a long time that it is practically unfeasible, so that
we might not have to worry at all about implementing this.
When one can print 1e9 lines per second (each line containing
a subset specification), it might still take more than
200000 years to print all subsets of a set with 64 elements.
However, during that time computers might become faster,
so that the task could be finished earlier, when the computer
is updated using hot hardware update capabilities while it
executes the program.
== 3 of 5 ==
Date: Sun, Feb 9 2014 3:13 am
From: Öö Tiib
On Sunday, 9 February 2014 10:39:48 UTC+2, Stefan Ram wrote:
> Dale Fletcher <dflach@twees.au> writes:
> >Good observation. Then there is a question of unmasking the bits.
>
> Do we need vectors assuming that 64-bit integer arithmetic
> is available? On one hand, some sets might have more than
> 64 elements. (In 1997, Harkstrøm et al. reported a set with
> more than 3000 elements!) On the other hand, printing all
> subsets from a set with more than 64 elements might take
> such a long time that it is practically unfeasible, so that
> we might not have to worry at all about implementing this.
It is quite optimal to use 'enum', 'std::bitset<32>' or just
'uint32_t' instead of 'std::set<type_that_has_32_states>'. Also
that 'std::bitset<3000>' can be often more viable than
'std::set<type_that_has_3000_states>'. Instead of 'std::vector'
I would suggest 'boost::container::flat_set' that takes care
of set-like behavior of underlying vector there.
> When one can print 1e9 lines per second (each line containing
> a subset specification), it might still take more than
> 200000 years to print all subsets of a set with 64 elements.
> However, during that time computers might become faster,
> so that the task could be finished earlier, when the computer
> is updated using hot hardware update capabilities while it
> executes the program.
The task to output all possible states of a set is indeed not too
useful when the amount of states grows. Learning to output state
of set (in all of its incarnations) is the handy skill there.
== 4 of 5 ==
Date: Sun, Feb 9 2014 3:46 am
From: ram@zedat.fu-berlin.de (Stefan Ram)
Öö Tiib <ootiib@hot.ee> writes:
>It is quite optimal to use 'enum', 'std::bitset<32>' or just
With <cstdint>::std::uint_least64_t one can do arithmetics
and get the next state by just »++«.
#include <iostream>
#include <ostream>
#include <cstdint>
#include <cassert>
void print( int const i, int const num )
{ for( int k = num - 1; k >= 0; --k )
::std::cout <<( char )( i &( 1 << k )? '`' + num - k : ' ' );
::std::cout << '\n'; }
void enumerate( int const num )
{ assert( num <= 64 );
using bits = ::std::uint_least64_t;
bits const top =( bits )1 << num;
for( bits i = 0; i <= top - 1; ++i )print( i, num ); }
int main(){ enumerate( 3 ); }
== 5 of 5 ==
Date: Sun, Feb 9 2014 4:20 am
From: Öö Tiib
On Sunday, 9 February 2014 13:46:59 UTC+2, Stefan Ram wrote:
> Öö Tiib <ootiib@hot.ee> writes:
> >It is quite optimal to use 'enum', 'std::bitset<32>' or just
>
> With <cstdint>::std::uint_least64_t one can do arithmetics
> and get the next state by just »++«.
Yes, that was my original point in start of this sub-thread.
In practice we rarely need to order states of set (nothing to
talk of finding next state of set). In practice we usually
need to insert, erase and count elements in it.
Inserting to integral variable used as set is done with '|='
erasing with '&=~' but efficient counting is tricky and I
bet that 'std::bitset' does it more efficiently than algorithm
of average Joe. ;)
==============================================================================
TOPIC: Return by reference
http://groups.google.com/group/comp.lang.c++/t/f6dd94c3223a1dbf?hl=en
==============================================================================
== 1 of 8 ==
Date: Sun, Feb 9 2014 3:50 am
From: Giuliano Bertoletti
Hello,
I've a classes like this:
class SubObject { ... };
class Object {
public:
SubObject sub;
};
class MyClass {
public:
Object obj;
public:
SubObject &GetSubObject() { return obj.sub; } // shortcut
};
which is the difference of calling?
==================
MyClass c;
SubObject &sub = c.GetSubObject();
SubObject sub = c.GetSubObject();
==================
It compiles both ways.
In practice I've an higher number of nested classes, so GetSubObject()
is actually a shortcut which digs deep into MyClass and retrieves the
item I need.
Giulio.
== 2 of 8 ==
Date: Sun, Feb 9 2014 4:04 am
From: Marcel Müller
On 09.02.14 12.50, Giuliano Bertoletti wrote:
> which is the difference of calling?
>
> ==================
> MyClass c;
>
> SubObject &sub = c.GetSubObject();
> SubObject sub = c.GetSubObject();
> ==================
The second line creates a copy of SubObject. It is in fact another
syntax for the following constructor call:
SubObject sub(GetSubObject());
This /might/ be expensive if copying SubObject is expensive. Furthermore
changes to sub do not apply to c.GetSubObject().
In general you should prefer references for non-trivial data types
unless you have good reasons not to do so.
Marcel
== 3 of 8 ==
Date: Sun, Feb 9 2014 4:07 am
From: ram@zedat.fu-berlin.de (Stefan Ram)
Giuliano Bertoletti <gbe32241@libero.it> writes:
>I've a classes like this:
»classes« è un plurale, mentre l'articolo »a« si usa soltanto
con il singolare. Inoltre, credo che quando non c'è un altro
verbo, si preferisce »have« oppure »'ve got« invece di »'ve«,
perché il verbo »have« è accentato.
>SubObject &sub = c.GetSubObject();
>SubObject sub = c.GetSubObject();
In the first case, »sub« becomes just another name for the object
that already exists as a field of the class instance.
In the second case, a new object is created and the state (value)
of the object that already exists as a field of the class instance
is /copied/ to that new object.
(However, I rarely use reference results, so I am not totally sure.)
#include <iostream>
#include <ostream>
struct alpha
{ int beta = 7;
int & gamma()
{ ::std::cout << " gamma: " << &beta << ": " << beta << '\n';
return beta; }};
int main()
{ alpha a;
int & delta = a.gamma();
::std::cout << " delta: " << &delta << ": " << delta << "\n\n";
int epsilon = a.gamma();
::std::cout << "epsilon: " << &epsilon << ": " << epsilon << "\n\n"; }
== 4 of 8 ==
Date: Sun, Feb 9 2014 4:58 am
From: Jorgen Grahn
On Sun, 2014-02-09, Marcel Müller wrote:
> On 09.02.14 12.50, Giuliano Bertoletti wrote:
>> which is the difference of calling?
>>
>> ==================
>> MyClass c;
>>
>> SubObject &sub = c.GetSubObject();
>> SubObject sub = c.GetSubObject();
>> ==================
>
> The second line creates a copy of SubObject. It is in fact another
> syntax for the following constructor call:
>
> SubObject sub(GetSubObject());
>
> This /might/ be expensive if copying SubObject is expensive. Furthermore
> changes to sub do not apply to c.GetSubObject().
>
> In general you should prefer references for non-trivial data types
> unless you have good reasons not to do so.
Depends a lot on the circumstances. If it's clear that the lifetime
of 'SubObject& sub' is shorter than whatever it's referencing, then
sure. If not ... very bad things can happen if the object dies and he
uses that reference to it.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
== 5 of 8 ==
Date: Sun, Feb 9 2014 4:05 am
From: Luca Risolia
Jorgen Grahn wrote:
> Depends a lot on the circumstances. If it's clear that the lifetime
> of 'SubObject& sub' is shorter than whatever it's referencing, then
> sure. If not ... very bad things can happen if the object dies and he
> uses that reference to it.
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
Object obj;
public:
std::shared_ptr<SubObject> GetSubObject() {
return std::shared_ptr<SubObject>(shared_from_this(), &obj.sub);
}
};
auto c = std::make_shared<MyClass>();
auto sub = c->GetSubObject(); // c.use_count() is 2
== 6 of 8 ==
Date: Sun, Feb 9 2014 5:07 am
From: Jorgen Grahn
On Sun, 2014-02-09, Giuliano Bertoletti wrote:
>
> Hello,
>
> I've a classes like this:
>
> class SubObject { ... };
>
> class Object {
> public:
> SubObject sub;
> };
>
> class MyClass {
> public:
> Object obj;
>
> public:
> SubObject &GetSubObject() { return obj.sub; } // shortcut
> };
>
> which is the difference of calling?
>
> ==================
> MyClass c;
>
> SubObject &sub = c.GetSubObject();
> SubObject sub = c.GetSubObject();
> ==================
>
> It compiles both ways.
>
> In practice I've an higher number of nested classes, so GetSubObject()
> is actually a shortcut which digs deep into MyClass and retrieves the
> item I need.
You might want to review that design to see if there is a smarter way
of doing it. You're saying you drill past three or more levels to get
that object, and that seems unusual. Perhaps your classes are too
much like dumb data containers, and you could change them to contain
more of the intelligence?
On the other hand, dumb data containers aren't always a bad idea ...
By the way, don't forget the third form:
const SubObject& sub = c.GetSubObject();
Here you're still at the mercy of whoever owns the object, but at
least you're promising not to modify it without informing the owner.
It's rather common to only need read access to something. This way
you can document it, and the code will IMO be significantly easier
to read.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
== 7 of 8 ==
Date: Sun, Feb 9 2014 4:21 am
From: Luca Risolia
Giuliano Bertoletti wrote:
> SubObject &sub = c.GetSubObject();
Don't return references to sub objects. To safely share (sub)objects in memory
use smart pointers.
> SubObject sub = c.GetSubObject();
This is a copy and is safe.
If you read the answer I have given in my other answer, you will probably see
the difference better.
== 8 of 8 ==
Date: Sun, Feb 9 2014 5:43 am
From: Giuliano Bertoletti
ok, thank you.
Is it then safe to call:
c.GetSubObject().SomeFunction()
and expect a straight invocation of the original subobject (not a copy)?
Giulio.
Il 09/02/2014 13.04, Marcel Müller ha scritto:
> On 09.02.14 12.50, Giuliano Bertoletti wrote:
>> which is the difference of calling?
>>
>> ==================
>> MyClass c;
>>
>> SubObject &sub = c.GetSubObject();
>> SubObject sub = c.GetSubObject();
>> ==================
>
> The second line creates a copy of SubObject. It is in fact another
> syntax for the following constructor call:
>
> SubObject sub(GetSubObject());
>
> This /might/ be expensive if copying SubObject is expensive. Furthermore
> changes to sub do not apply to c.GetSubObject().
>
> In general you should prefer references for non-trivial data types
> unless you have good reasons not to do so.
>
>
> Marcel
>
==============================================================================
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
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment