我有这个问题,我之前想过这个问题,但认为回答并非易事
int x = x + 1;
int main() {
return x;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果程序的行为是有效的,那么它是否被定义或未定义.如果定义了,那么x已知的值是main多少?
正如初始化所述,需要进行左值到右值的转换?是int x = x;UB吗?C++标准在3.3.2 声明部分中有一个令人惊讶的例子,其中a int用它自己的不确定值初始化:
Run Code Online (Sandbox Code Playgroud)int x = 12; { int x = x; }这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]
Johannes对此问题的回答表明是未定义的行为,因为它需要左值到右值的转换.
在最新的C++ 14草案标准中N3936,可以在此处找到此示例已更改为:
Run Code Online (Sandbox Code Playgroud)unsigned char x = 12; { unsigned char x = x; }这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]
C++ 14中有关于不确定值和未定义行为的变化,这些变化在示例中引发了这种变化吗?
C++标准包含一个半着名的例子,在3.3.2中的"令人惊讶的"名称查找,"声明点":
int x = x;
Run Code Online (Sandbox Code Playgroud)
这初始化x自身,(原始类型)未初始化,因此具有不确定的值(假设它是一个自动变量).
这实际上是未定义的行为吗?
根据4.1"左值到右值转换",对未初始化的值执行左值到右值的转换是未定义的行为.右手是否x接受这种转换?如果是这样,示例实际上会有未定义的行为吗?
我刚刚在一个函数中找到了这行代码,这让我很困惑.这在任何情况下都有意义,还是未定义的行为?
char * acFilename = acFilename;
Run Code Online (Sandbox Code Playgroud)
编辑:编译器抱怨警告C4700,我正在使用未初始化的变量.
我不小心通过数组中的自引用在程序中创建了一个错误.这是一个非常简化的演示程序,在概念上类似:
#include <iostream>
using namespace std;
int kTest[] = {
kTest[0]
};
int main() {
cout << kTest[0] << endl;
}
Run Code Online (Sandbox Code Playgroud)
我很惊讶我既没有收到编译错误,也没有收到关于此代码的警告!在我的情况下,它最终产生不可预测的输出.它是否访问垃圾内存?
我很好奇在什么情况下这将有明确定义的输出(如果有的话!).
编辑:是否有所作为,如果kTest是static?怎么样const?都?
我最近在代码审查中遇到了这个与C++静态初始化顺序相关的查询.
在这里,我想知道在调用静态对象构造函数之前是否保证静态成员变量被初始化?
MyClass.h:
typedef int (*MyFunc)(int);
class MyClass {
MyClass(MyFunc fptr) {
mFunc = fptr;
}
static MyFunc mFunc;
}
Run Code Online (Sandbox Code Playgroud)
MyClass.cpp:
MyFunc MyClass::mFunc = nullptr;
Run Code Online (Sandbox Code Playgroud)
MyDifferentClass.h:
MyDifferentClass {
public:
static int MyStaticFunc(int);
}
Run Code Online (Sandbox Code Playgroud)
MyDifferentClass.cpp:
static MyClass myClassObj(MyDifferentClass::MyStaticFunc);
Run Code Online (Sandbox Code Playgroud)
在代码中,将在创建之前mFunc初始化为?查询的原因是如果订单不能保证,那么可能会再次初始化为.nullptrmyClassObjmFuncnullptr
如果具有静态存储持续时间的对象的C++构造函数未初始化成员,那么是否需要保留先前的零初始化,或者是否使成员具有不确定的值?
我对C++规范的解读是它与自身相矛盾.
例:
#include <iostream>
struct Foo { Foo(); int x; } object;
Foo::Foo() { }
int main() { std::cout << object.x << std::endl; }
Run Code Online (Sandbox Code Playgroud)
Foo()构造函数没有显式初始化成员object.x,因此根据12.6.2第8段中的注释:
该成员具有不确定的价值.
但是,通过各种初始化的细节,这似乎是不正确的.成员object.x由于具有静态存储持续时间而被零初始化,然后我看不到任何改变它的东西.
关于构造函数,适用的12.6.2中的文本是:
该实体是默认初始化的.
在8.5第7段中,默认初始化的相关情况是:
......没有执行初始化
我读到这意味着默认初始化不会改变先前的零初始化.
我是否遗漏了一些其他文本,它们在构造函数调用开始时将所有成员重置为"不确定值"?
我在stackoverflow上发现了关于零初始化和默认初始化的各种其他问题,但我看不到任何分析在默认初始化跟随同一实体的早期初始化之后会发生什么.
在这种情况下,可能没有实际效果.但是在一个更复杂的构造函数中,一些成员被初始化而其他成员没有,编译器是否必须准确地跟踪哪些字节/位被初始化?或者它是否只是初始化整个对象(例如,将构造函数简化为memset()调用) )?
我有以下代码,在gcc和clang上表现得如预期的那样.但是,MSVC给了我一个意想不到的结果.
让我们先看看有问题的代码.
#include <iostream>
// -----------------------------------------------
class Test // Dummy for MCVE
{
public:
Test();
void Print();
private:
int arr[5];
};
Test tst;
// -----------------------------------------------
template<typename T>
struct range // some stuff not needed by example removed
{
constexpr range(T n) : b(0), e(n) {}
constexpr range(T b, T e) : b(b), e(e) {}
struct iterator
{
T operator*() { return i; }
iterator& operator++() { ++i; return *this; }
bool operator!=(iterator other) { return i != other.i ; } …Run Code Online (Sandbox Code Playgroud) 受到" 使用编译时HTML解析的C++ HTML模板引擎 "的想法的启发,我试图编写一个示例类来检查字符串中的第一个字符是否是a.
int dummy[0];
class Test
{
public:
constexpr Test(const char *p):p_(p){}
constexpr void check()const
{
if (p_[0]!='a')
dummy[1]=0;
}
const char *p_;
};
constexpr Test operator"" _test(const char *pszText, size_t)
{
Test t(pszText);
t.check();
return t;
}
int main()
{
//dummy[1] = 0;
constexpr Test t = "baa"_test;
}
Run Code Online (Sandbox Code Playgroud)
它运行良好(UCCntu上的GCC7.1).如果第一个char不是a,它将给出编译错误:
main.cpp:29:24: error: array subscript value ‘1’ is outside the bounds
of array ‘dummy’ of type ‘int [0]’
constexpr Test t = "baa"_test;
Run Code Online (Sandbox Code Playgroud)
令我感到困惑的是,如果我将代码更改为: …