Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > is &(vector[0]) always valid?

Reply
Thread Tools

is &(vector[0]) always valid?

 
 
Jorgen Grahn
Guest
Posts: n/a
 
      01-20-2007
["Followup-To:" header set to comp.lang.c++.]

On Sat, 20 Jan 2007 07:21:08 GMT, John Salmon <> wrote:
>
> I was under the impression that the following was always valid:
>
> std::vector<T> v;
> .
> T *p = &(v[0]);
>
> But I was recently told that care was needed in case the vector was
> empty, i.e., when v.size() == 0.


Or when v.empty().

..
> or do I have to write:
>
> T *p = (v.size()!=0)? &(v[0]) : 0;


That, or:

T *p = v.empty()? 0: &(v[0]);

std::vector<T>::size() is constant time, I think, but that's not the case
for other containers. So when you really want to test for (non-)emptiness,
it's good to make a habit of using empty().

/Jorgen

--
// Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
\X/ snipabacken.dyndns.org> R'lyeh wgah'nagl fhtagn!

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
 
 
 
whyglinux
Guest
Posts: n/a
 
      01-20-2007
John Salmon wrote:
> I was under the impression that the following was always valid:
>
> std::vector<T> v;
> .
> T *p = &(v[0]);
>
> But I was recently told that care was needed in case the vector was
> empty, i.e., when v.size() == 0.
>
> I'm hoping that the above expression is fine, even if v is empty, but
> that if you try to dereference p, you're in trouble.
>
> If the above isn't ok, I'd have to write:
>
> T *p = (v.size()!=0)? &(v[0]) : 0;
>
> I took a look in the C++98 standard, and couldn't find anything to
> confirm my hope. I see from Table 68 that the expression has the
> "operational sematics" of
>
> &(*(v.begin() + 0))
>
> which sure *seems* like it might in turn be "operationally equivalent"
> to v.begin(), which sure seems safe, even for an empty vector. But I
> now feel myself to be on very thin ice.
>
> So, can I write:
>
> T *p = &(v[0]);
>
> or do I have to write:
>
> T *p = (v.size()!=0)? &(v[0]) : 0;
>
> Thanks,
> John Salmon
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]


Yes, it's undefined.

v[0] is equivalent to *v.begin(). Whether v is an empty vector or not,
v.begin() returns a valid iterator. But if v is empty, v.begin(), like
v.end(), is not a valid dereferenceable iterator, so *v.begin() is
undefined.

Note though, &(*(v.begin() + 0)) is not, as you said, "operationally
equivalent" to v.begin() because v.begin() returns an object of the
vector<T>'s iterator type while &(*(v.begin() + 0)) should return a
type of pointer to T (since operator * is overloaded here), and the
iterator type needs not to be the same as a pointer to T.

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
 
 
 
Lynn
Guest
Posts: n/a
 
      01-20-2007
> std::vector<T> v;
> .
> T *p = &(v[0]);


This works in Visual C++ 2003. It crashes when the size is
zero in Visual C++ 2005. I fixing this all over our code right
now.

> But I was recently told that care was needed in case the vector was
> empty, i.e., when v.size() == 0.


Yes, true.

> If the above isn't ok, I'd have to write:
>
> T *p = (v.size()!=0)? &(v[0]) : 0;


Yes, this should work OK.

Lynn


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
david.hinkes@gmail.com
Guest
Posts: n/a
 
      01-22-2007

John Salmon wrote:
> I was under the impression that the following was always valid:
>
> std::vector<T> v;
> .
> T *p = &(v[0]);
>



I've often had this question myself. Even if this worked, isn't it
_very_ dangerous? Consider the following:

std::vector<T> v(1);

T dummy;

v.push_back(dummy);

T * p = &(v[0]);


v.push_back(dummy);

v.push_back(dummy);

// does p still point to anything valid at this point? Since the
push_back operations, perhaps
// internally the vector resized itself. I wouldn't expect that the
vector object keep the same internal
// memory.

T first_element = p[0]; //is p still valid?

// Thoughts?

Dave

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
James Dennett
Guest
Posts: n/a
 
      01-22-2007
wrote:
> John Salmon wrote:
>> I was under the impression that the following was always valid:
>>
>> std::vector<T> v;
>> .
>> T *p = &(v[0]);
>>

>
>
> I've often had this question myself. Even if this worked, isn't it
> _very_ dangerous? Consider the following:
>
> std::vector<T> v(1);
>
> T dummy;
>
> v.push_back(dummy);
>
> T * p = &(v[0]);
>
>
> v.push_back(dummy);
>
> v.push_back(dummy);
>
> // does p still point to anything valid at this point? Since the
> push_back operations, perhaps
> // internally the vector resized itself. I wouldn't expect that the
> vector object keep the same internal
> // memory.
>
> T first_element = p[0]; //is p still valid?
>
> // Thoughts?


This is spelled out quite clearly; after a push_back that
can cause a vector to grow beyond its capacity, iterators
and pointers to its old elements are invalidated. In your
example, p is invalidated by the first call to v.push_back
after p was initialized.

It's dangerous is people don't know the rules on when
iterators and pointers are invalidated, but those rules
are vital to safe use of containers in any case.

Further discussion on this line is probably best removed
from comp.std.c++; followups set.

-- James

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      01-22-2007
* John Salmon:
>
> So, can I write:
>
> T *p = &(v[0]);
>
> or do I have to write:
>
> T *p = (v.size()!=0)? &(v[0]) : 0;


The latter.

§23.1/7 "If the container is empty, then 'begin() == end()'".
§24.1/5 Explaining that one-past-the-end iterators are past-the-end
values, then "The library never assumes that past-the-end values are
dereferencable".

Hence v[0] by equivalence to &(*(begin()+0)) performs an invalid
dereferencing when the vector is empty. In more practical terms, the
vector need not have a buffer if it's empty. But I suspect that with
most compiler and standard library implementations (all?) you can get
away with it if the vector's /capacity/ is greater than zero.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
Clark S. Cox III
Guest
Posts: n/a
 
      01-22-2007
John Salmon wrote:
> I was under the impression that the following was always valid:
>
> std::vector<T> v;
> ..
> T *p = &(v[0]);
>
> But I was recently told that care was needed in case the vector was
> empty, i.e., when v.size() == 0.


You were told correctly. Calling v[x], where x is >= v.size() is
undefined behavior; period.

> I'm hoping that the above expression is fine, even if v is empty, but
> that if you try to dereference p, you're in trouble.
>
> If the above isn't ok, I'd have to write:
>
> T *p = (v.size()!=0)? &(v[0]) : 0;
>
> I took a look in the C++98 standard, and couldn't find anything to
> confirm my hope. I see from Table 68 that the expression has the
> "operational sematics" of
>
> &(*(v.begin() + 0))
>
> which sure *seems* like it might in turn be "operationally equivalent"
> to v.begin(), which sure seems safe, even for an empty vector. But I
> now feel myself to be on very thin ice.
>
> So, can I write:
>
> T *p = &(v[0]);
>
> or do I have to write:
>
> T *p = (v.size()!=0)? &(v[0]) : 0;


You have to write the later (or some variation thereof).

--
Clark S. Cox III


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      01-22-2007
"Alf P. Steinbach" wrote:
> * John Salmon:


> > So, can I write:


> > T *p = &(v[0]);


> > or do I have to write:


> > T *p = (v.size()!=0)? &(v[0]) : 0;


> The latter.


> §23.1/7 "If the container is empty, then 'begin() == end()'".
> §24.1/5 Explaining that one-past-the-end iterators are past-the-end
> values, then "The library never assumes that past-the-end values are
> dereferencable".


> Hence v[0] by equivalence to &(*(begin()+0)) performs an invalid
> dereferencing when the vector is empty. In more practical terms, the
> vector need not have a buffer if it's empty. But I suspect that with
> most compiler and standard library implementations (all?) you can get
> away with it if the vector's /capacity/ is greater than zero.


Changing the capacity doesn't make it work with g++ nor with
VC++. There are thus at least two major implementations (the
two most widely used?) where it actually does fail at runtime.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
Reply With Quote
 
peter koch
Guest
Posts: n/a
 
      01-23-2007

James Kanze wrote:
> "Alf P. Steinbach" wrote:
> > * John Salmon:

>
> > > So, can I write:

>
> > > T *p = &(v[0]);

>
> > > or do I have to write:

>
> > > T *p = (v.size()!=0)? &(v[0]) : 0;

>
> > The latter.

>
> > §23.1/7 "If the container is empty, then 'begin() == end()'".
> > §24.1/5 Explaining that one-past-the-end iterators are past-the-end
> > values, then "The library never assumes that past-the-end values are
> > dereferencable".

>
> > Hence v[0] by equivalence to &(*(begin()+0)) performs an invalid
> > dereferencing when the vector is empty. In more practical terms, the
> > vector need not have a buffer if it's empty. But I suspect that with
> > most compiler and standard library implementations (all?) you can get
> > away with it if the vector's /capacity/ is greater than zero.

>
> Changing the capacity doesn't make it work with g++ nor with
> VC++. There are thus at least two major implementations (the
> two most widely used?) where it actually does fail at runtime.


Which is logical. I do not know of a hardware platform where
&(*begin()) would physically access memory, so I'd expect &(*begin())
to return a pointer in all cases when the implementation does not
perform some kind of explicit check. And that check would be related
to size, not capacity.

/Peter


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

 
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
Wireless Lan on/off switch always litup Terry Wireless Networking 1 08-14-2005 07:15 PM
File copy always interrupted over wireless network =?Utf-8?B?TWF0cml4Y3ViZWQ=?= Wireless Networking 1 02-28-2005 06:00 PM
Why do I always have to repair my network connection after rebooti =?Utf-8?B?Q29uZnVzZWRfQ29uc3VtZXI=?= Wireless Networking 2 11-28-2004 02:24 PM
belkin 54g always works on 11 Mbps hans Wireless Networking 2 11-03-2004 01:17 PM
Trying to create a CSS box that is always is always the width of an image placed inside it (and no wider) Deryck HTML 4 06-22-2004 08:25 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57