473,394 Members | 2,168 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Safe to swap through pointer to vector?

I am utilizing a std::vector<int>, but due to a platform-specific reason
(Managed C++, but this is irrelevant), in order to include it as a
member of a class, I have to work with a pointer to it. However, I can
declare concrete std::vectors as local variables in functions.

Therefore, I would like to know whether the following construct is safe,
i.e., there is no memory leak or undefined behavior. The demonstration
example doesn't need all the class boilerplate so I left that out.

Specifically, is it safe to call vector::swap() through a pointer to a
vector? As far as I can reason, it should be OK, and adding output
statements shows that *pv has the correct values, but I want to confirm
whether or not this is undefined behavior that just happens to work by
coincidence.
#include <vector>

int main()
{
using std::vector;

vector<int>* pv = new vector<int>; // This represents my class variable
vector<intv; // This represents the local variable

for (int i = 0; i < 3; ++i) {
v.push_back(i);
}

pv->swap(v); // <----- I would like to know if this is safe

delete pv;
}

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Feb 9 '07 #1
7 3416
Marcus Kwok wrote:
#include <vector>

int main()
{
using std::vector;

vector<int>* pv = new vector<int>; // This represents my class variable
vector<intv; // This represents the local variable

for (int i = 0; i < 3; ++i) {
v.push_back(i);
}

pv->swap(v); // <----- I would like to know if this is safe
Yes, it is safe.
Feb 9 '07 #2
Marcus Kwok wrote:
I am utilizing a std::vector<int>, but due to a platform-specific reason
(Managed C++, but this is irrelevant), in order to include it as a
member of a class, I have to work with a pointer to it. However, I can
declare concrete std::vectors as local variables in functions.

Therefore, I would like to know whether the following construct is safe,
i.e., there is no memory leak or undefined behavior. The demonstration
example doesn't need all the class boilerplate so I left that out.

Specifically, is it safe to call vector::swap() through a pointer to a
vector? As far as I can reason, it should be OK, and adding output
statements shows that *pv has the correct values, but I want to confirm
whether or not this is undefined behavior that just happens to work by
coincidence.
#include <vector>

int main()
{
using std::vector;

vector<int>* pv = new vector<int>; // This represents my class
variable
vector<intv; // This represents the local variable

for (int i = 0; i < 3; ++i) {
v.push_back(i);
}

pv->swap(v); // <----- I would like to know if this is safe

delete pv;
}
The swap is fine. However, there is an exception safety problem in your
code: should the v.push_back(i) at some point throw, the pv pointee will
not be deallocated during stack unwinding. You should consider try-catch or
using a smart pointer instead of a raw pointer.
Best

Kai-Uwe Bux
Feb 9 '07 #3
Kai-Uwe Bux <jk********@gmx.netwrote:
Marcus Kwok wrote:
>#include <vector>

int main()
{
using std::vector;

vector<int>* pv = new vector<int>; // This represents my class
variable
vector<intv; // This represents the local variable

for (int i = 0; i < 3; ++i) {
v.push_back(i);
}

pv->swap(v); // <----- I would like to know if this is safe

delete pv;
}

The swap is fine. However, there is an exception safety problem in your
code: should the v.push_back(i) at some point throw, the pv pointee will
not be deallocated during stack unwinding. You should consider try-catch or
using a smart pointer instead of a raw pointer.
Thanks (and thanks to Noah as well). In the real code, pv is a class
member that is allocated in a constructor and deleted in a destructor.
I elided that from this example in order to minimize the code, but your
point is well taken.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Feb 10 '07 #4
Marcus Kwok wrote:
Kai-Uwe Bux <jk********@gmx.netwrote:
>Marcus Kwok wrote:
>>#include <vector>

int main()
{
using std::vector;

vector<int>* pv = new vector<int>; // This represents my class
variable
vector<intv; // This represents the local variable

for (int i = 0; i < 3; ++i) {
v.push_back(i);
}

pv->swap(v); // <----- I would like to know if this is safe

delete pv;
}

The swap is fine. However, there is an exception safety problem in your
code: should the v.push_back(i) at some point throw, the pv pointee will
not be deallocated during stack unwinding. You should consider try-catch
or using a smart pointer instead of a raw pointer.

Thanks (and thanks to Noah as well). In the real code, pv is a class
member that is allocated in a constructor and deleted in a destructor.
That sure is good. By and in itself, however, it does not eliminate the
problem. Probably, I am not going to tell you anything you don't know, but
since it somehow illustrates the trickyness of getting pointers exception
safe, I will say it anyway. Consider:

class X {

vector<int>* pv;

public:

~X ( void ) {
delete pv;
}

X ( void )
: pv ( new vector<int() );
{}

// so far everything is fine. But:

X ( some_type some_data )
: pv ( new vector<int() )
{
// populate pv:
// if this throws, our destructor will not be called !!!
}

};

Therefore, constructors that initialize pointees have to take care of
cleaning up their own allocation mess.

Also, as soon as you have two pointer members in you class, allocation of
the second may throw and cause the first to leak. Pointers are just a pain.

I elided that from this example in order to minimize the code, but your
point is well taken.

Best

Kai-Uwe Bux
Feb 10 '07 #5
Kai-Uwe Bux wrote:
Marcus Kwok wrote:
>Kai-Uwe Bux <jk********@gmx.netwrote:
>>Marcus Kwok wrote:
#include <vector>

int main()
{
using std::vector;

vector<int>* pv = new vector<int>; // This represents my class
variable
vector<intv; // This represents the local variable

for (int i = 0; i < 3; ++i) {
v.push_back(i);
}

pv->swap(v); // <----- I would like to know if this is safe

delete pv;
}
The swap is fine. However, there is an exception safety problem in your
code: should the v.push_back(i) at some point throw, the pv pointee will
not be deallocated during stack unwinding. You should consider try-catch
or using a smart pointer instead of a raw pointer.
Thanks (and thanks to Noah as well). In the real code, pv is a class
member that is allocated in a constructor and deleted in a destructor.

That sure is good. By and in itself, however, it does not eliminate the
problem. Probably, I am not going to tell you anything you don't know, but
since it somehow illustrates the trickyness of getting pointers exception
safe, I will say it anyway. Consider:

class X {

vector<int>* pv;

public:

~X ( void ) {
delete pv;
}

X ( void )
: pv ( new vector<int() );
{}

// so far everything is fine. But:

X ( some_type some_data )
: pv ( new vector<int() )
{
// populate pv:
// if this throws, our destructor will not be called !!!
}

};

Therefore, constructors that initialize pointees have to take care of
cleaning up their own allocation mess.
auto_ptr to the rescue:
class X {

auto_ptr<vector<int pv;

public:
//No need for a destructor

X ( void )
: pv ( new vector<int() )
{}

X ( some_type some_data )
: pv ( new vector<int() )
{
// populate pv:
// if this throws, pv's destructor *will* called
}
};
--
Clark S. Cox III
cl*******@gmail.com
Feb 10 '07 #6
Kai-Uwe Bux <jk********@gmx.netwrote:
That sure is good. By and in itself, however, it does not eliminate the
problem. Probably, I am not going to tell you anything you don't know, but
since it somehow illustrates the trickyness of getting pointers exception
safe, I will say it anyway. Consider:

class X {

vector<int>* pv;

public:

~X ( void ) {
delete pv;
}

X ( void )
: pv ( new vector<int() );
{}

// so far everything is fine. But:

X ( some_type some_data )
: pv ( new vector<int() )
{
// populate pv:
// if this throws, our destructor will not be called !!!
}

};

Therefore, constructors that initialize pointees have to take care of
cleaning up their own allocation mess.
True. In my specific case, it is being used in the implementation of a
GUI window which will not be copyable.
Also, as soon as you have two pointer members in you class, allocation of
the second may throw and cause the first to leak. Pointers are just a pain.
Yes, I found that these articles helped illuminate for me many of the
intricacies of pointer usage:

(mind the long URIs):
http://icu.sourceforge.net/docs/pape..._operator.html

and the update to the article:
http://icu.sourceforge.net/docs/pape...revisited.html

Of course, if I had my way, I wouldn't use pointers in this case either,
but I am forced to due to the constraints of the framework (.NET) that
the GUI must be implemented in.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Feb 13 '07 #7
Clark S. Cox III <cl*******@gmail.comwrote:
Kai-Uwe Bux wrote:
>Therefore, constructors that initialize pointees have to take care of
cleaning up their own allocation mess.

auto_ptr to the rescue:
class X {

auto_ptr<vector<int pv;

public:
//No need for a destructor

X ( void )
: pv ( new vector<int() )
{}

X ( some_type some_data )
: pv ( new vector<int() )
{
// populate pv:
// if this throws, pv's destructor *will* called
}
};
Yes, a similar technique is used in the articles I linked to in another
post, though in the context of writing an assignment operator.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Feb 13 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Steve Hill | last post by:
Hi, suppose I have a vector allocated on the heap. Can I use a temporary (stack based vector) and swap to clear it, or is this unsafe. e.g. vector<int> *v; vector<int> tmp; v->swap(tmp); // is...
8
by: Generic Usenet Account | last post by:
To settle the dispute regarding what happens when an "erase" method is invoked on an STL container (i.e. whether the element is merely removed from the container or whether it also gets deleted in...
10
by: Steven T. Hatton | last post by:
I read Stroustrup's article of the day: http://www.research.att.com/~bs/C++.html Programming with Exceptions. InformIt.com. April 2001. http://www.research.att.com/~bs/eh_brief.pdf Some of...
7
by: Mikhail N. Kupchik | last post by:
Hi All. I have a question regarding Herb Sutter's idiom of implementation of operator= via nonthrowing swap() member function, to guarantee strict exception safety. The idea of the idiom is...
20
by: Sacha | last post by:
Consider I have a working thread like this, while (1) { if ( g_pObject ) g_pObject->DoOneStep(); } with an class hierarchie like this
28
by: Protoman | last post by:
I'd like to now if this smart pointer class if thread-safe: Code: // COPYRIGHT CMDR DOUGLAS I. PEREIRA 07/10/06 // ALL UNAUTHORIZED THIRD PARTY USE IS PROHIBITED // I HAVE WORKED VERY HARD...
21
by: T.A. | last post by:
I understand why it is not safe to inherit from STL containers, but I have found (in SGI STL documentation) that for example bidirectional_iterator class can be used to create your own iterator...
9
by: ma740988 | last post by:
Consider: # include <vector> # include <iostream> # include <cstdlib> # include <ctime> bool ispow2i ( double n ) {
3
by: Nindi73 | last post by:
Hi, I am in need of a deep copy smart pointer (Boost doesn't provide one) which doesnt require the contained types to have a virtual copy constructor. I wrote a smart pointer class that I think...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.