How to make the vector size unchanged but values not?

S

shuisheng

Dear All,

I have a question. Assume

#include <vector>
using namespace std;

class A
{
private:
vector<int> v;
int n;

public:
void Reset(int i)
{
n = i;
v.resize(i);
}

vector<int>& Vector()
{
return v;
}
};

For class A, 'n' and the size of 'v' must be always consistent. Every
time n is changed, v is reset with the size n. If n is not changed,
the vector v's size can not change, but its values can change, such as

A::Vector()[2] = 3;

But user can use A::Vector().resize() to change the size of the
vector. How can I avoid it and still keep all the std::vector 's
functions to change the values?

Thanks and best regards,

Shuisheng
 
K

Kai-Uwe Bux

shuisheng said:
Dear All,

I have a question. Assume

#include <vector>
using namespace std;

class A
{
private:
vector<int> v;
int n;

public:
void Reset(int i)
{
n = i;
v.resize(i);
}

vector<int>& Vector()
{
return v;
}
};

For class A, 'n' and the size of 'v' must be always consistent. Every
time n is changed, v is reset with the size n. If n is not changed,
the vector v's size can not change, but its values can change, such as

A::Vector()[2] = 3;

But user can use A::Vector().resize() to change the size of the
vector. How can I avoid it and still keep all the std::vector 's
functions to change the values?

The easy way is to ditch the variable i. Since it cannot be observed from
the outside, it does not make any sense to carry it around. Probably this
possibility is due to oversimplification of the problem and does not arise
in the original setting.

The standard way would be to not expose the internal vector by means of a
Vector() method but to narrow down its interface and make the needed
functions available through forwarding. They would also update i.

The hard way would be to not return a reference in the Vector() method, but
a smart reference that updates i upon destruction. Since we cannot overload
the dot-operator, there are some limitations to this method. We can,
however, return a smart pointer.


All in all, you seem to have a design problem that is best solved by
avoiding the problem. What is the underlying conundrum that you are
struggling with?


Best

Kai-Uwe Bux
 
S

shuisheng

shuisheng said:
Dear All,
I have a question. Assume
#include <vector>
using namespace std;
class A
{
private:
  vector<int> v;
  int n;
public:
  void Reset(int i)
  {
    n = i;
    v.resize(i);
  }
  vector<int>& Vector()
  {
    return v;
  }
};
For class A, 'n' and the size of 'v' must be always consistent. Every
time n is changed, v is reset with the size n. If n is not changed,
the vector v's size can not change, but its values can change, such as
A::Vector()[2] = 3;
But user can use A::Vector().resize() to change the size of the
vector. How can I avoid it and still keep all the std::vector 's
functions to change the values?

The easy way is to ditch the variable i. Since it cannot be observed from
the outside, it does not make any sense to carry it around.  Probably this
possibility is due to oversimplification of the problem and does not arise
in the original setting.

The standard way would be to not expose the internal vector by means of a
Vector() method but to narrow down its interface and make the needed
functions available through forwarding. They would also update i.

The hard way would be to not return a reference in the Vector() method, but
a smart reference that updates i upon destruction. Since we cannot overload
the dot-operator, there are some limitations to this method. We can,
however, return a smart pointer.

All in all, you seem to have a design problem that is best solved by
avoiding the problem. What is the underlying conundrum that you are
struggling with?

Best

Kai-Uwe Bux

The underlying problem is like that: I have a 2-D (two dimensional)
field (or array), the field points are arranged regularly along x and
y axis, which looks like a grid as follows,

y2 . . . .
y1 . . . .
y0 . . . .
x0 x1 x2 x3

where the dots denote field points. Given two vectors: xv and yv, the
grid points will be well defined. And the 2-D field have a size of
(size of xv) by (size of yv). So every time reset xv and yv, the size
of 2-D field will changed. But if the xv and yv do not change, only
the field values can change. For 2-D filed/array, I use blitz::array,
which is similar to std::vector but is 2-D.

Thank you for your help!
 
K

Kai-Uwe Bux

shuisheng said:
shuisheng said:
Dear All,
I have a question. Assume
#include <vector>
using namespace std;
class A
{
private:
vector<int> v;
int n;
public:
void Reset(int i)
{
n = i;
v.resize(i);
}
vector<int>& Vector()
{
return v;
}
};
For class A, 'n' and the size of 'v' must be always consistent. Every
time n is changed, v is reset with the size n. If n is not changed,
the vector v's size can not change, but its values can change, such as
A::Vector()[2] = 3;
But user can use A::Vector().resize() to change the size of the
vector. How can I avoid it and still keep all the std::vector 's
functions to change the values?

The easy way is to ditch the variable i. Since it cannot be observed from
the outside, it does not make any sense to carry it around.  Probably
this possibility is due to oversimplification of the problem and does not
arise in the original setting.

The standard way would be to not expose the internal vector by means of a
Vector() method but to narrow down its interface and make the needed
functions available through forwarding. They would also update i.

The hard way would be to not return a reference in the Vector() method,
but a smart reference that updates i upon destruction. Since we cannot
overload the dot-operator, there are some limitations to this method. We
can, however, return a smart pointer.

All in all, you seem to have a design problem that is best solved by
avoiding the problem. What is the underlying conundrum that you are
struggling with?

Best

Kai-Uwe Bux

The underlying problem is like that: I have a 2-D (two dimensional)
field (or array), the field points are arranged regularly along x and
y axis, which looks like a grid as follows,

y2 . . . .
y1 . . . .
y0 . . . .
x0 x1 x2 x3

where the dots denote field points. Given two vectors: xv and yv, the
grid points will be well defined. And the 2-D field have a size of
(size of xv) by (size of yv). So every time reset xv and yv, the size
of 2-D field will changed. But if the xv and yv do not change, only
the field values can change. For 2-D filed/array, I use blitz::array,
which is similar to std::vector but is 2-D.

Hm, the least invasive I can think of, is to split the setter/getter
function in two:

vector< int > const & get_x ( void ) const {
return xy;
}

void set_x ( vector< int > const & val ) {
xy = val;
// do whatever is needed to update the 2d-array
}

// similarly for y.

However, getter and setter methods still smell NotSoGood(tm). The preferred
way of going about this is to make the vectors and the 2d-array strictly
private members of the class and to devise an interface that describes how
an object of that type responds to messages. That way, proper encapsulation
is ensured. That, however, will require a good deal of knowledge about the
application domain where this class will be used.


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top