C++;使用对正在定义的变量的引用 是下面的代码有效C++,根据标准(折扣…s)?< /P>
大家都知道这个项目使用的GCC版本(4.1.2和3.2.3…甚至不要让我开始…)进行编译,但是应该吗C++;使用对正在定义的变量的引用 是下面的代码有效C++,根据标准(折扣…s)?< /P>,c++,scope,language-lawyer,self-reference,object-lifetime,C++,Scope,Language Lawyer,Self Reference,Object Lifetime,大家都知道这个项目使用的GCC版本(4.1.2和3.2.3…甚至不要让我开始…)进行编译,但是应该吗 编辑:我添加了一些细节,例如关于f()在原始代码中的概念外观。基本上,它意味着在某些条件下初始化x。语法上是这样,但是如果您尝试这样做 #include <iostream> using namespace std; typedef int T; bool f(T& x) { return true; } int main() { T x = (f(x) ?
编辑:我添加了一些细节,例如关于f()在原始代码中的概念外观。基本上,它意味着在某些条件下初始化x。语法上是这样,但是如果您尝试这样做
#include <iostream>
using namespace std;
typedef int T;
bool f(T& x)
{
return true;
}
int main()
{
T x = (f(x) ? x : T());
cout << x;
}
然后输出10。
在第一种情况下,声明对象x
,编译器会指定一些伪任意值(因此您不会初始化它),而在第二种情况下,您会在声明后指定一个值(T()
,即0
),即初始化它
我认为你的问题与此类似:
它无疑应该编译,但可能有条件地导致未定义的行为。
- 如果
是非基本类型,则未定义行为(如果已分配)T
- 如果
是基元类型,如果它是非本地的,则为定义良好的行为;如果在读取之前未指定,则为未定义的行为(字符类型除外,其中定义为提供未指定的值)T
本标准的相关部分是第3.8节“对象寿命: 类型为
T
的对象的生存期从以下时间开始:
- 获得T型的适当对齐和尺寸的存储,以及
- 如果对象具有非平凡的初始化,其初始化已完成。
x
的生存期还没有开始。在同一节中,我们找到了使用x
进行管理的规则:
类似地,在对象的生存期开始之前,但在对象将占用的存储已分配之后,或者在对象的生存期结束之后,在对象占用的存储被重用或释放之前,可以使用引用原始对象的任何glvalue,但只能以有限的方式使用。对于正在建造或破坏的物体,见12.7。否则,此类glvalue指的是已分配的存储(3.7.4.2),使用glvalue的属性(不依赖于其值)是明确定义的。如果出现以下情况,则程序具有未定义的行为:
- 将左值到右值的转换(4.1)应用于此类glvalue,
- glvalue用于访问非静态数据成员或调用对象的非静态成员函数,或
- glvalue绑定到对虚拟基类(8.5.3)的引用,或
- glvalue用作动态_转换(5.2.7)的操作数或typeid的操作数
T::operator=
的调用。句号,根据案例2,这是未定义的行为
原语类型是在不调用成员函数的情况下分配的,所以现在让我们仔细看看第4.1节“左值到右值的转换”,看看左值到右值的转换何时会是未定义的行为:
当未赋值操作数或其子表达式(第5条)中发生左值到右值的转换时,不访问被引用对象中包含的值。在所有其他情况下,转换结果根据以下规则确定:
- 如果
是(可能是cv限定的)T
,则结果是一个空指针常量(4.10)std::nullptr\u T
- 否则,如果
具有类类型,则转换副本将从glvalue初始化类型为T
的临时值,并且转换的结果是临时值的prvalueT
- 否则,如果glvalue引用的对象包含无效指针值(3.7.4.2、3.7.4.3),则该行为是实现定义的
- 否则,如果
是(可能是cv限定的)无符号字符类型(3.9.1),并且glvalue引用的对象包含不确定值(5.3.4、8.5、12.6.2),并且该对象没有自动存储持续时间,或者glvalue是一元T
运算符的操作数,或者绑定到引用,结果是一个未指定的值。&
- 否则,如果glvalue引用的对象包含不确定值,则行为未定义。
- 否则,glvalue指示的对象中包含的值就是prvalue结果
f()
时,变量x
有一个不确定的值。只要该变量具有基元类型,并且在读取之前赋值(读取是左值到右值的转换),代码就可以了
如果变量在读取之前未赋值,则效果取决于t
。字符类型将导致代码执行并使用任意但合法的字符值。所有其他类型都会导致未定义的行为
1除非
x
具有静态存储持续时间,例如全局变量。在这种情况下,根据第3.6.2节非局部变量的初始化,执行前初始化为零:
具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)的变量应在进行任何其他初始化之前进行零初始化(8.5)
在这种静态存储持续时间的情况下,不可能运行到lval
#include <iostream>
using namespace std;
typedef int T;
bool f(T& x)
{
return true;
}
int main()
{
T x = (f(x) ? x : T());
cout << x;
}
bool f(T& x)
{
x = 10;
return true;
}
#include <stdio.h>
struct A {
A() { printf("A::A() %p\n", this); }
A(const A& a) { printf("A::A(const A&) %p %p\n", this, &a); }
~A() { printf("A::~A() %p\n", this); }
};
int main()
{
A a=a;
}
A::A(const A&) 0253FDD8 0253FDD8
A::~A() 0253FDD8
r = ...;