我将这个缩小了:
struct A
{
int * x;
A() : x( x = new int() )
{
}
};
请翻译为:
int m = m = 3;
//or
struct X;
//...
X x = x = X();
在我看来,这似乎是合法的。我不知道你为什么想这样做,但这是合法的吗?是否有需要这样做的情况(不包括int
情况,我意识到那完全没有用)?
我将这个缩小了:
struct A
{
int * x;
A() : x( x = new int() )
{
}
};
请翻译为:
int m = m = 3;
//or
struct X;
//...
X x = x = X();
在我看来,这似乎是合法的。我不知道你为什么想这样做,但这是合法的吗?是否有需要这样做的情况(不包括int
情况,我意识到那完全没有用)?
这要看你如何定义“合法”。它会被编译,但这并不意味着它一定能正常工作。
在完整语句X x = ...
执行之前,x
是未初始化的。它还不是一个X
。因此,执行x = X()
意味着创建一个临时X
并在未初始化的变量x
上调用X::operator=(const X&)
。
对于尚未初始化(其构造函数尚未被调用)的非POD类实例调用函数将导致未定义的行为。如果X
是POD类型(或在C++11中是平凡的),那么它可以工作。但否则就不行。
这样的语法是合法的,但在运行时会导致未定义的行为。就像这样的语句:
X x = x = X();
第二个 =
是赋值操作符,它将值赋给一个未初始化的变量。(第一个 =
仅仅是语法上的复制初始化,表示后面的值被用于初始化;它不是赋值。)
这是合法的语法。X在其自身定义的范围内。你可能想要一个对象引用它自己的情况是循环链表,类似于:
struct Node {
Node( Node *pNext_ ) : pNext( pNext_ ) {
}
// ...
Node *pNext;
};
Node empty( &empty };
这个空列表包含一个指向自身的虚拟节点。这既是明确定义的,也是有用的。请注意,我们获取了空的地址,即使Node是非POD类型并且尚未构造,这也是合法的。我认为允许像你的int m = m = 3;
示例中那样的赋值并不直接有用,但是对于语言来说,很难允许我的而不允许你的。
要了解如何将其应用于成员构造函数,请考虑:
struct A {
Node list;
A() : list( &list ) {}
}
一旦名称在范围内,允许对其进行赋值和从中赋值也变得可能。
Node empty( &empty };
,其中对象 empty
用自身进行初始化。我的编辑附加了解释:“要了解这是如何实现的...”。但感谢您取消了负评。 - BrangdonpNext( pNext_ )
误导了。 :) 你是对的,在这种情况下加1 :) - Luchian Grigoreint m = m = 3;
//or
struct X;
//...
X x = x = X();
这是合法的(如果你定义了一个名为X的结构体,但你的结构体名字是A,而且你不需要用C++写结构体),但两者都是未定义行为。
x(x = new int())
也是合法的,但也有未定义的行为。
y = A()
这行代码是在一个未初始化的变量上调用了operator=
函数吗? - R. Martinho Fernandesx(x = new int())
而不是像通常一样使用x(new int())
。但是如果简化版本是合法的,那么原始版本也是合法的,对吧? - Luchian Grigoreint x = x++;
也是!),但不确定第一个或第三个。需要一些研究。成员的初始化器与创建新变量并不相同,这是我所知道的。 - Mr Lister