![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Slime <pov### [at] slimeland com> wrote:
> > In C++ in particular this is another situation were the majority
> of C++
> > programmers out there have no idea what's wrong:
> Are you just referring to the lack of copy constructor and assignment
> operator, or is there something more subtle here?
Since I was talking about completely trivial errors that the majority
of C++ programmers can't see, what do you think?
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Le_Forgeron <jgr### [at] free fr> wrote:
> * you used a template ? (nop, just a red herring for you! but a single
> uppercase letter is usually preferred to Value_t)
Preferred by who? A single uppercase letter is only obfuscation.
> * you have the [] checks the upper range (whereas usually it's at()
> which check, and [] do not)
I'm not creating a C++ standard container. If the class specs say that
an assertion failure will happen on an invalid index, then it's ok.
> * you checked upper range, but not lower one
Why would I check a lower range when std::size_t is by definition
unsigned? ("index >= 0" is always true.)
> * you should have stated index in [] with const
Why? It doesn't make any difference from the outside, and the
implementation is trivial.
> * using assert is not the right way to handle the issue.
It depends on how you spec the class. It's certainly the *easiest* way
of doing it.
> * you did not test in creator the value of size ( 0 ?)
"new Value_t[0]" is perfectly valid C++ and will not cause malfunction.
> * copy-constructor... you're in trouble with mData
That's the problem with the class.
> * you did not disable automatic conversion of "number" into Array<>, so
> if you have some different signature for some methods using either
> number or Array<>, you're in for surprise (explicit)
Maybe.
> * you forget the include needed for size_t (cstring)
> * you forget the declaration of assert() (assert.h)
I skipped #include lines for brevity. (Besides, std::size_t is officially
declared in <cstddef>.)
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> On 3/4/2012 14:33, Warp wrote:
> > return mData[index];
> Given the previous discussion, I'm betting this is the error Warp was
> talking about - returning the address of a variable that gets disposed when
> this object gets disposed.
No. It's not returning a reference to a local variable. Returning a
reference to a member variable is standard practice (for example all
standard data containers do that.) You wouldn't be able to modify the
members of the array using operator [] from the outside otherwise.
(In the const version of the operator it would be possible to return
the element by value. However, this is not usually done because the
members might be heavy to copy.)
(Yes, it would be possible for the calling code to define a reference
or pointer to the array element and keep it for longer than the lifetime
of the array. However, that kind of error is no different from doing it
with raw arrays or any other type of data container. A class acting as
a wrapper for a data container cannot guard the calling code from this.)
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Le_Forgeron <lef### [at] free fr> wrote:
> void foobar()
> {
> Array<int> foo(3);
> Array<int> bar(foo); // get a copy of foo
> } // you definitely have a problem with glibc here!
You don't need anything more than that.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp escreveu:
> John VanSickle <evi### [at] kosher hotmail com> wrote:
>> Evidently not. In chatting with the interviewers that day, they all
>> confirmed that most bugs are stupid things like this.
>
> Sadly, the vast majority of people programming in C (or C++) professionally
> out there don't actually know the language enough to avoid such trivial ways
> to shoot yourself in the foot. It may be something that you and me can spot
> in a second, but I'm certain the average professional C programmer can't see
> it. It's no wonder programs are so buggy. A sad state of affairs.
>
> In C++ in particular this is another situation were the majority of C++
> programmers out there have no idea what's wrong:
>
> //-------------------------------------------------------------
> template<typename Value_t>
> class Array
> {
> Value_t* mData;
> std::size_t mSize;
>
> public:
> Array(std::size_t size):
> mData(new Value_t[size]),
> mSize(size)
> {}
>
> ~Array() { delete[] mData; }
>
> Value_t& operator[](std::size_t index)
> {
> assert(index < mSize);
> return mData[index];
> }
>
> const Value_t& operator[](std::size_t index) const
> {
> assert(index < mSize);
> return mData[index];
> }
> };
the C issues were self-evident, but this is not much easier than trying
to read some idiomatic haskell... :P
BTW, why
Array(std::size_t size):
mData(new Value_t[size]),
mSize(size)
{}
rather than
Array(std::size_t size)
{
mData=new Value_t[size];
mSize=size;
}
when you've got exactly 2 extra chars (:,) in the first case? Don't
tell me it's because some compile-time initialization that is not done
in the second case...
is also delete[] defined when you define those operator[] methods?
C++ is so alien...
--
a game sig: http://tinyurl.com/d3rxz9
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 3/5/2012 11:13 AM, nemesis wrote:
> BTW, why
>
> Array(std::size_t size):
> mData(new Value_t[size]),
> mSize(size)
> {}
>
> rather than
>
> Array(std::size_t size)
> {
> mData=new Value_t[size];
> mSize=size;
> }
>
> when you've got exactly 2 extra chars (:,) in the first case? Don't tell
> me it's because some compile-time initialization that is not done in the
> second case...
It's because the second case doesn't initialize the variables, but
rather assigns to them. This distinction matters in C++, and in general
here's how the code plays out in the two cases when you instantiate the
class:
case 1:
1 - call mData constructor with parameter `new Value_t[size]'
2 - call mSize constructor with parameter `size'
case2:
1 - call no-parameter mData constructor
2 - call no-parameter mSize constructor
3 - call mData assignment operator with parameter `new Value_t[size]'
4 - call mSize assignment operator with parameter `size'
In this particular case I think the code generated by most compilers
would be identical, but the former is better practice since in other
situations the generated code will be different. There's also cases
where the second case won't even compile, for instance if one of the
member fields lacks a zero-parameter constructor.
> is also delete[] defined when you define those operator[] methods?
delete[] is built in to the language and frees the memory associated
with a call to an array allocation performed with new[].
> C++ is so alien...
Depends on what languages you feel at home in, obviously.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
nemesis <nam### [at] gmail com> wrote:
> BTW, why
> Array(std::size_t size):
> mData(new Value_t[size]),
> mSize(size)
> {}
> rather than
> Array(std::size_t size)
> {
> mData=new Value_t[size];
> mSize=size;
> }
> when you've got exactly 2 extra chars (:,) in the first case? Don't
> tell me it's because some compile-time initialization that is not done
> in the second case...
Using the initialization list is recommended and, in some cases,
actually the only possible way of initializing certain members.
Usually you write actual code in the constructor only if a member
cannot be constructed in the initialization list. (In this particular
example there's no discernible benefit, except perhaps for a consistent
style of initialization.)
Examples of members that can only be initialized in the initialization
list are const members, references and objects with no default constructor.
Also, even if the object had a default constructor but you wanted to
initialize with a different constructor, the only way to do that is to
do it in the initialization list.
//-------------------------------------------------------------------
class ClassWithoutDefaultConstructor
{
public:
ClassWithoutDefaultConstructor(int);
};
class ClassWithAdditionalConstructors
{
public:
ClassWithAdditionalConstructors();
ClassWithAdditionalConstructors(int);
};
class Example
{
int& referenceMember;
const std::string constMember;
ClassWithoutDefaultConstructor obj1;
ClassWithAdditionalConstructors obj2;
public:
Example(int& aReference):
referenceMember(aReference),
constMember("Hello"),
obj1(5),
obj2(10)
{
// none of the above can be initialized here
}
};
//-------------------------------------------------------------------
> is also delete[] defined when you define those operator[] methods?
operator[] has nothing to do with new[] and delete[].
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On 3/5/2012 12:05, Warp wrote:
>> mData(new Value_t[size]),
> example there's no discernible benefit, except perhaps for a consistent
> style of initialization.)
WOuldn't it also be safer if that 'new' call threw an exception?
--
Darren New, San Diego CA, USA (PST)
People tell me I am the counter-example.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |