指向成员数据问题的指针 [英] Pointer to member data problems

查看:57
本文介绍了指向成员数据问题的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下类包含一系列

值的起点和终点。范围可以具有从开始和结束的相对顺序暗示的方向,或者可以没有方向。 IOW

如果start大于end,而direction == true,那么范围

有反方向。如果direction == false,起点是

总是小于终点。


例如,为了使两个范围的交集变得更容易,我还想要保持标准化的价格。开始和结束的开始<结束

即使真正的开始大于结束。由于模板

参数E(对于元素类型)可以是任何东西,我不想

生成可能昂贵的起始和结束元素副本如果

它们是用户定义的类型。因此,我决定尝试将这个

信息存储在指向会员的指针中。


大部分时间这都可行。但对于负向

方向的范围,虽然elem_ptr成员显然指向正确的成员(即反转),当我取消引用它们时,我得到了

错误数据:例如this-> * m_pNormalizedStart将返回m_start而不是m_end的
,尽管调试器为m_pNormalizedStart显示& Range< int,int> :: m_end"


我知道我可以使用成员函数返回规范化数据

并且只需要将m_start与m_end进行比较。这不会是一个问题,

因为它可以内联,但我想知道一般情况下是否使用

指向这样的成员就可以了。


有什么腥的东西吗?关于我如何在构造函数中设置成员指针

?我知道在成员初始化时,对象还没有完全构建起来。但是,会员数据首先被初始化

因此应该有一个有效的地址。


我也认为编译器可能正在处理
成员喜欢静态数据(因为这是设置他们的

值的语法)并在创建一个新的Range时使用

不同的方向覆盖它们。但是,我假设每个Range对象都会有一组不同的成员指针。也许这不是有效的

假设?


我希望我只是犯了一些其他愚蠢的错误,但我看了

很难,还没有找到任何东西。我不认为这是一个编译器错误

,因为我在运行我在

GCC和Borland上编译的测试代码时会得到相同的行为。


这是一些骨架代码:


//声明:


模板< typename E,typename D = E>

类范围

{

typedef E Range :: * elem_ptr;

public:

范围< E,D> ::范围()

:m_start()

,m_end()

,m_directed(false )

,m_pNormalizedStart(& Range :: m_start)

,m_pNormalizedEnd(& Range :: m_end){;}


范围< E,D> ::范围(const E& startElem

,const E& endElem

,bool导演)

:m_start(导演?

startElem :( startElem> endElem?endElem:startElem))

,m_end(导演?

endElem: (startElem< endElem?endElem:startElem))

,m_directed(定向)

,m_pNormalizedS tart(m_start< = m_end?

& Range :: m_start:& Range :: m_end)

,m_pNormalizedEnd(m_start< = m_end?

& Range :: m_end:& Range :: m_start){;}

//等等

私人:

E m_start;

E m_end;

bool m_directed;

elem_ptr m_pNormalizedStart;

elem_ptr m_pNormalizedEnd; < br $>
};


TIA


-

Bob Hairgrove
No**********@Home.com

解决方案

2004年7月3日星期六16:40:45 +0200,Bob Hairgrove

< wo ********* *****@to.know>写道:


oops ...构造函数是从不同的文件中复制和粘贴的。

这是他们应该看的样子:
< blockquote class =post_quotes> template< typename E,typename D = E>
class Range
{
typedef E Range :: * elem_ptr;
public:
范围()
:m_start()
,m_end()
,m_directed(false)
,m_pNormalizedStart(& Range :: m_start)
,m_pNormalizedEnd(& ; Range :: m_end){;}

范围(const E& startElem
,const E& endElem
,bool指示)
:m_start(指导) ?
startElem :( startElem> endElem?endElem:startElem))
,m_end(指示?
endElem:(startElem< endElem?endElem:startElem))
,m_directed (指示)
,m_pNormalizedStart(m_start< = m_end?
& Range :: m_start:& Range :: m_end)
,m_pNormalizedEnd(m_start< = m_end?
& Range :: m_end:& Range :: m_start){;}
//等
私人:
E m_start;
E m_end;
bool m_directed;
elem_ptr m_pNormalizedStart;
elem_ptr m_pNormalizedEnd;
};




-

Bob Hairgrove
No**********@Home.com


2004年7月3日星期六16:40:45 +0200,Bob Hairgrove

< wo *********** ***@to.know>写道:

以下类包含一系列
值的起点和终点。范围可以具有从开始和结束的相对顺序隐含的方向,或者可以没有方向。 IOW
如果start大于end,而direction == true,那么范围
有反方向。如果direction == false,则起点始终小于终点。

为了使两个范围的交集更容易,例如,我也想要保持标准化的开始和结束的开始<结束
即使真正的开始大于结束。由于模板
参数E(对于元素类型)可以是任何东西,我不想生成可能昂贵的起始和结束元素副本,如果它们是用户定义的类型。因此,我决定尝试将这些信息存储在指向成员的指针中。

大部分时间这都可行。但是对于具有负方向的范围,虽然elem_ptr成员显然指向正确的成员(即反转),但当我取消引用它们时,我得到了错误的数据:例如this-> * m_pNormalizedStart将返回m_start而不是m_end,尽管调试器为m_pNormalizedStart显示& Range< int,int> :: m_end

我知道我可以使用成员函数返回规范化数据
并且只需要将m_start与m_end进行比较。这不会是一个问题,
因为它可以内联,但我想知道一般情况下是否使用
指向这样的成员就可以了。

是那里有腥的东西。关于我如何在构造函数中设置成员指针
?我知道在成员初始化时对象还没有完全构建好;然而,成员数据首先被初始化,因此应该有一个有效的地址。

我还认为编译器可能会像静态数据那样处理指针。这是设置其
值的语法,并在创建具有不同方向的新范围时覆盖它们。但是,我假设每个Range对象都有一组不同的指向成员的指针。也许这不是一个有效的假设吗?

我希望我只是犯了一些其他愚蠢的错误,但我看起来很难,但还没找到任何东西。我不认为这是一个编译器错误
因为我在运行我在GCC和Borland上编译的测试代码时会得到相同的行为。

这是一些骨架代码:



为我工作,看不出有什么不对。


#include< iostream>

使用命名空间std;


模板< typename E,typename D = E>

类范围

{

typedef E Range :: * elem_ptr;

public:

Range()

:m_start()

,m_end()

,m_directed(false)

,m_pNormalizedStart(& Range :: m_start)

,m_pNormalizedEnd(&范围:: m_end){;}


范围(const E& startElem

,const E& endElem

, bool导演)

:m_start(导演?

startElem :( startElem> endElem?endElem:startElem))

,m_end(导演?

endElem :( startElem< endElem?endElem:startElem))

,m_directed(定向)

,m_pNormalizedStart(m_start< = m_end?

& Range :: m_start:& Range :: m_end)

,m_pNormalizedEnd(m_start< = m_end?

& Range :: m_end:& Range :: m_start){;}

//等

void dump()

{

cout<< this-> * m_pNormalizedStart<< ''\ n'';

cout<< this-> * m_pNormalizedEnd<< ''\ n'';

}

私人:

E m_start;

E m_end;

bool m_directed;

elem_ptr m_pNormalizedStart;

elem_ptr m_pNormalizedEnd;

};


int main()

{

范围< int> r(20,10,true);

范围< int> s(10,20,true);

r.dump();

s.dump();

}


输出


10

20

10

20


john


2004年7月3日星期六16:40:45 +0200,Bob Hairgrove

< wo ************** @ to.know>写道:

以下类包含一系列
值的起点和终点。范围可以具有从开始和结束的相对顺序隐含的方向,或者可以没有方向。 IOW
如果start大于end,而direction == true,那么范围
有反方向。如果direction == false,则起点始终小于终点。

为了使两个范围的交集更容易,例如,我也想要保持标准化的开始和结束的开始<结束
即使真正的开始大于结束。由于模板
参数E(对于元素类型)可以是任何东西,我不想生成可能昂贵的起始和结束元素副本,如果它们是用户定义的类型。因此,我决定尝试将这些信息存储在指向成员的指针中。




您可以使用普通指针,甚至可以使用引用。


john


The following class contains start and end points of a range of
values. The range can have a direction which is implied from the
relative order of start and end, or it can be without direction. IOW
if start is greater than end, and direction == true, then the range
has reverse direction. If direction == false, the starting point is
always less than the end point.

To make getting the intersection of two ranges easier, for example, I
also want to keep a "normalized" start and end for which start < end
even if the real start is greater than the end. Since the template
parameter E (for element type) can be anything, I don''t want to
generate possibly expensive copies of the start and end elements if
they are user-defined types. Therefore, I decided to try storing this
information in pointers to members.

Most of the time this works OK. But for ranges with negative
direction, although the elem_ptr members are apparently pointing to
the correct members (i.e. reversed), when I dereference them I get the
wrong data: e.g. this->*m_pNormalizedStart will return m_start instead
of m_end, although the debugger is showing "&Range<int,int>::m_end"
for m_pNormalizedStart.

I know I can just use a member function to return the normalized data
and only need to compare m_start to m_end. That wouldn''t be a problem,
also since it could be inlined, but I want to know in general if using
pointers to members like this is OK.

Is there something "fishy" about how I am setting the member pointers
in the constructor? I know that the object isn''t fully constructed yet
at member initialization time; however, the member data is initialized
first and therefore should have a valid address.

I also thought that the compiler might be treating the pointers to
memebers like static data (since that is the syntax for setting their
value) and overwriting them when a new Range is created with a
different direction. However, I assume that each Range object would
have a distinct set of pointers to member. Maybe this isn''t a valid
assumption?

I hope I am just making some other stupid mistake, but I have looked
hard and not yet found anything. I don''t think it is a compiler bug
because I get the same behavior when running my test code compiled on
GCC and Borland.

Here is some skeleton code:

// declarations:

template<typename E, typename D = E>
class Range
{
typedef E Range::*elem_ptr;
public:
Range<E,D>::Range()
: m_start()
, m_end()
, m_directed(false)
, m_pNormalizedStart(&Range::m_start)
, m_pNormalizedEnd(&Range::m_end){;}

Range<E,D>::Range(const E & startElem
, const E & endElem
, bool directed)
: m_start( directed ?
startElem : (startElem > endElem ? endElem : startElem))
, m_end ( directed ?
endElem : (startElem < endElem ? endElem : startElem))
, m_directed(directed)
, m_pNormalizedStart(m_start <= m_end ?
&Range::m_start : &Range::m_end)
, m_pNormalizedEnd(m_start <= m_end ?
&Range::m_end : &Range::m_start){;}
// etc.
private:
E m_start;
E m_end;
bool m_directed;
elem_ptr m_pNormalizedStart;
elem_ptr m_pNormalizedEnd;
};

TIA

--
Bob Hairgrove
No**********@Home.com

解决方案

On Sat, 03 Jul 2004 16:40:45 +0200, Bob Hairgrove
<wo**************@to.know> wrote:

oops ... constructors were copied and pasted from a different file.
Here''s how they should look:

template<typename E, typename D = E>
class Range
{
typedef E Range::*elem_ptr;
public:
Range()
: m_start()
, m_end()
, m_directed(false)
, m_pNormalizedStart(&Range::m_start)
, m_pNormalizedEnd(&Range::m_end){;}

Range(const E & startElem
, const E & endElem
, bool directed)
: m_start( directed ?
startElem : (startElem > endElem ? endElem : startElem))
, m_end ( directed ?
endElem : (startElem < endElem ? endElem : startElem))
, m_directed(directed)
, m_pNormalizedStart(m_start <= m_end ?
&Range::m_start : &Range::m_end)
, m_pNormalizedEnd(m_start <= m_end ?
&Range::m_end : &Range::m_start){;}
// etc.
private:
E m_start;
E m_end;
bool m_directed;
elem_ptr m_pNormalizedStart;
elem_ptr m_pNormalizedEnd;
};



--
Bob Hairgrove
No**********@Home.com


On Sat, 03 Jul 2004 16:40:45 +0200, Bob Hairgrove
<wo**************@to.know> wrote:

The following class contains start and end points of a range of
values. The range can have a direction which is implied from the
relative order of start and end, or it can be without direction. IOW
if start is greater than end, and direction == true, then the range
has reverse direction. If direction == false, the starting point is
always less than the end point.

To make getting the intersection of two ranges easier, for example, I
also want to keep a "normalized" start and end for which start < end
even if the real start is greater than the end. Since the template
parameter E (for element type) can be anything, I don''t want to
generate possibly expensive copies of the start and end elements if
they are user-defined types. Therefore, I decided to try storing this
information in pointers to members.

Most of the time this works OK. But for ranges with negative
direction, although the elem_ptr members are apparently pointing to
the correct members (i.e. reversed), when I dereference them I get the
wrong data: e.g. this->*m_pNormalizedStart will return m_start instead
of m_end, although the debugger is showing "&Range<int,int>::m_end"
for m_pNormalizedStart.

I know I can just use a member function to return the normalized data
and only need to compare m_start to m_end. That wouldn''t be a problem,
also since it could be inlined, but I want to know in general if using
pointers to members like this is OK.

Is there something "fishy" about how I am setting the member pointers
in the constructor? I know that the object isn''t fully constructed yet
at member initialization time; however, the member data is initialized
first and therefore should have a valid address.

I also thought that the compiler might be treating the pointers to
memebers like static data (since that is the syntax for setting their
value) and overwriting them when a new Range is created with a
different direction. However, I assume that each Range object would
have a distinct set of pointers to member. Maybe this isn''t a valid
assumption?

I hope I am just making some other stupid mistake, but I have looked
hard and not yet found anything. I don''t think it is a compiler bug
because I get the same behavior when running my test code compiled on
GCC and Borland.

Here is some skeleton code:


Works for me, can''t see anything wrong.

#include <iostream>
using namespace std;

template<typename E, typename D = E>
class Range
{
typedef E Range::*elem_ptr;
public:
Range()
: m_start()
, m_end()
, m_directed(false)
, m_pNormalizedStart(&Range::m_start)
, m_pNormalizedEnd(&Range::m_end){;}

Range(const E & startElem
, const E & endElem
, bool directed)
: m_start( directed ?
startElem : (startElem > endElem ? endElem : startElem))
, m_end ( directed ?
endElem : (startElem < endElem ? endElem : startElem))
, m_directed(directed)
, m_pNormalizedStart(m_start <= m_end ?
&Range::m_start : &Range::m_end)
, m_pNormalizedEnd(m_start <= m_end ?
&Range::m_end : &Range::m_start){;}
// etc.
void dump()
{
cout << this->*m_pNormalizedStart << ''\n'';
cout << this->*m_pNormalizedEnd << ''\n'';
}
private:
E m_start;
E m_end;
bool m_directed;
elem_ptr m_pNormalizedStart;
elem_ptr m_pNormalizedEnd;
};

int main()
{
Range<int> r(20, 10, true);
Range<int> s(10, 20, true);
r.dump();
s.dump();
}

Output

10
20
10
20

john


On Sat, 03 Jul 2004 16:40:45 +0200, Bob Hairgrove
<wo**************@to.know> wrote:

The following class contains start and end points of a range of
values. The range can have a direction which is implied from the
relative order of start and end, or it can be without direction. IOW
if start is greater than end, and direction == true, then the range
has reverse direction. If direction == false, the starting point is
always less than the end point.

To make getting the intersection of two ranges easier, for example, I
also want to keep a "normalized" start and end for which start < end
even if the real start is greater than the end. Since the template
parameter E (for element type) can be anything, I don''t want to
generate possibly expensive copies of the start and end elements if
they are user-defined types. Therefore, I decided to try storing this
information in pointers to members.



You could just use ordinary pointers, or maybe even references.

john


这篇关于指向成员数据问题的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆