Use pointers to Partitions in PartitionVector class (#759726)

The PartitionVector class is now internally using pointers to Partition
objects and taking on management of their lifetimes.  It therefore has
to implement the Big 3: destructor, copy constructor and copy assignment
operator [1][2].  This is because the implicitly-defined copy
constructor and assignment operator perform memberwise "shallow copying"
and the destructor does nothing.  This not correct for classes which
contain non-class types such as raw pointers.

The semantics of the interface still copies each Partition object into
the PartitionVector when they are added with push_back() and insert().

Note that a PartitionVector object is explicitly copy assigned in
Win_GParted::Refresh_Visual().  They are also implicitly copied when
(1) the implementing vector is resized larger to allow it to hold more
pointers to Partition objects than it previously had capacity for; and
(2) a Partition object is copied including the logicals PartitionVector
member.

[1] The rule of three/five/zero
    http://en.cppreference.com/w/cpp/language/rule_of_three
[2] Rule of Three
    https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29

Bug 759726 - Implement Partition object polymorphism
This commit is contained in:
Mike Fleetwood 2015-06-16 22:34:59 +01:00 committed by Curtis Gedak
parent 48d898ebfd
commit 06b8a3a14a
4 changed files with 108 additions and 16 deletions

View File

@ -14,9 +14,9 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* Minimal implementation of a class that behaves like a std::vector<Partition> which can
* be used in it's place with minimal change to the existing GParted code which expects to
* be working with a std::vector<Partition>.
/* Minimal implementation of a class with some behaviours like a std::vector<Partition>.
* However internally the class manages pointers to Partition objects allowing for
* Partition object polymorphism.
* Reference:
* C++ Reference to std::vector
* http://www.cplusplus.com/reference/vector/vector/
@ -44,10 +44,13 @@ class PartitionVector; // mutually recursive classes.
class PartitionVector {
public:
typedef size_t size_type;
typedef std::vector<Partition>::iterator iterator;
typedef std::vector<Partition *>::iterator iterator;
PartitionVector() {};
~PartitionVector() {};
PartitionVector( const PartitionVector & src );
~PartitionVector();
void swap( PartitionVector & other );
PartitionVector & operator=( PartitionVector rhs );
// Iterators
iterator begin() { return v.begin(); };
@ -56,22 +59,21 @@ public:
bool empty() const { return v.empty(); };
// Element access
Partition & operator[]( size_type n ) { return v[n]; };
const Partition & operator[]( size_type n ) const { return v[n]; };
Partition & operator[]( size_type n ) { return *v[n]; };
const Partition & operator[]( size_type n ) const { return *v[n]; };
size_type size() const { return v.size(); };
const Partition & front() const { return v.front(); };
const Partition & back() const { return v.back(); };
const Partition & front() const { return *v.front(); };
const Partition & back() const { return *v.back(); };
// Modifiers
void pop_back() { v.pop_back(); };
void erase( const iterator position ) { v.erase( position ); };
void clear() { v.clear(); };
void push_back( const Partition & partition ) { v.push_back( partition ); };
void insert( iterator position, const Partition & partition )
{ v.insert( position, partition ); };
void pop_back();
void erase( const iterator position );
void clear();
void push_back( const Partition & partition );
void insert( iterator position, const Partition & partition );
private:
std::vector<Partition> v;
std::vector<Partition *> v;
};
} //GParted

View File

@ -31,6 +31,7 @@ src/OperationLabelFileSystem.cc
src/OperationNamePartition.cc
src/OperationResizeMove.cc
src/Partition.cc
src/PartitionVector.cc
src/SWRaid_Info.cc
src/TreeView_Detail.cc
src/Utils.cc

View File

@ -47,6 +47,7 @@ gpartedbin_SOURCES = \
OperationNamePartition.cc \
OperationResizeMove.cc \
Partition.cc \
PartitionVector.cc \
PipeCapture.cc \
Proc_Partitions_Info.cc \
SWRaid_Info.cc \

88
src/PartitionVector.cc Normal file
View File

@ -0,0 +1,88 @@
/* Copyright (C) 2015 Mike Fleetwood
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "../include/Partition.h"
#include "../include/PartitionVector.h"
#include <algorithm>
namespace GParted
{
PartitionVector::PartitionVector( const PartitionVector & src )
{
v.resize( src.size() );
for ( unsigned int i = 0 ; i < src.size() ; i ++ )
v[i] = new Partition( src[i] );
}
PartitionVector::~PartitionVector()
{
for ( unsigned int i = 0 ; i < v.size() ; i ++ )
delete v[i];
}
void PartitionVector::swap( PartitionVector & other )
{
std::swap( this->v, other.v );
}
PartitionVector & PartitionVector::operator=( PartitionVector rhs )
{
// Copy assignment implemented using copy-and-swap idiom.
// 1) Pass-by-value to get rhs variable copy constructed from source;
// 2) Swap contents of this PartitionVector with rhs variable copy;
// 3) Method returns, rhs variable goes out of scope and destructor called on old
// this PartitionVector to delete owned Partitions.
// Reference:
// Wikibooks: More C++ Idioms / Copy-and-swap
// https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap
rhs.swap( *this );
return *this;
}
void PartitionVector::pop_back()
{
delete v.back();
v.pop_back();
}
void PartitionVector::erase( const iterator position )
{
delete *position;
v.erase( position );
}
void PartitionVector::clear()
{
for ( unsigned int i = 0 ; i < v.size() ; i ++ )
delete v[i];
v.clear();
}
void PartitionVector::push_back( const Partition & partition )
{
Partition * p = new Partition( partition );
v.push_back( p );
}
void PartitionVector::insert( iterator position, const Partition & partition )
{
Partition * p = new Partition( partition );
v.insert( position, p );
}
} //GParted