指向成员数据问题的指针 [英] Pointer to member data problems
问题描述
以下类包含一系列
值的起点和终点。范围可以具有从开始和结束的相对顺序暗示的方向,或者可以没有方向。 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屋!