如何强制编译器将非零值设置为未初始化的变量?
How to force compiler to set a non-zero value to uninitialized variables?
我正在玩C++ value initialization。
因此,我正在打印未初始化的值,以便根据 C++ 标准版本突出显示(未)初始化。
但是未初始化的值通常传达零值:-(
变量未初始化如何高亮?
(即,如何告诉编译器为未初始化的变量使用特定值?)
也许这可以使用 magic 用户提供的分配器来完成...
编辑: 我的以下代码片段不适用于生产。我只是想检查 C++ 标准关于 uninitialization/value-initialization/zero-initialization/default-initialization 机制的实现(通过编译器)。我不希望有关未初始化变量的编译器警告。我不想使用 MemoryCheckers。我只想强调编译器零初始化一些变量,默认初始化一些其他变量并且不初始化所有其他变量。并且这种初始化行为还取决于 C++ Standard 的版本。如果您认为最好的方法是使用编译器警告或 MemoryCheckers,请使用以下代码片段提供答案。
如果您已经理解我的问题,请不要阅读下面的详细尝试。
你可以build/run my first snippet on Coliru
#include <iostream>
struct A {
A() {} // user-defined default ctor does not initialize i
int i;
};
struct B {
A a;
};
int main()
{
std::cout << B().a.i << '\n';
// Results: C++03 -> uninitialized
// C++11 -> zero-initialized
std::cout << B{}.a.i << '\n';
// Results: C++03 -> Do not compile - B{} is correct since C++11
// C++11 -> uninitialized because
// DR1301 defines B{} as an aggregate-initialization
} // => A is value-initialized using the user-defined ctor
当使用 -std=c++03
编译时,执行可能会打印一个零值,但我更喜欢一个非零值。
0
使用-std=c++11
可能的输出
0
1208617840
另一个可能的输出使用-std=c++11
0
-201855824
但是 my more advanced snippet 现在未初始化对象的值为零 B{}.a.i
:-(
#include <iostream>
struct A {
A() {} // user-defined ctor does not initialize i
int i;
};
struct B {
A a;
};
int main()
{
std::cout <<"-----------"<< __cplusplus <<"-----------" "\n";
std::cout <<"B().a.i = "<< B().a.i <<'\n';
std::cout <<"B{}.a.i = "<< B{}.a.i <<'\n';
int d;
d = 42;
std::cout <<"(new(&d) B )->a.i = "<< (new(&d) B )->a.i <<'\n';
d = 42;
std::cout <<"(new(&d) B())->a.i = "<< (new(&d) B())->a.i <<'\n';
d = 42;
std::cout <<"(new(&d) B{})->a.i = "<< (new(&d) B{})->a.i <<'\n';
}
Build/Run 输出:
> g++ -std=c++03 -Wall -Wextra -pedantic main.cpp && ./a.out
-----------199711-----------
B().a.i = 0
(new(&d) B )->a.i = 42
(new(&d) B())->a.i = 0
> g++ -std=c++11 -Wall -Wextra -pedantic main.cpp && ./a.out
-----------201103-----------
B().a.i = 0
B{}.a.i = 0
(new(&d) B )->a.i = 42
(new(&d) B())->a.i = 0
(new(&d) B{})->a.i = 0
> g++ -std=c++14 -Wall -Wextra -pedantic main.cpp && ./a.out
-----------201402-----------
B().a.i = 0
B{}.a.i = 0
(new(&d) B )->a.i = 42
(new(&d) B())->a.i = 0
(new(&d) B{})->a.i = 0
一种可能的解决方案是使用 clang++
而不是 g++
。
clang++
v3.7 在我的特定情况下突出显示了未初始化的值。
注:此答案基于 C++ value initialization 自 C++11 以来已更改。值初始化是当 parentheses/braces 为空时: T(); T{}; new T(); new T{};
Build/Run Coliru
上的片段下方
#include <iostream>
struct A
{
A() {} // ctor does not initialize 'i'
int i;
};
struct B // implicit ctor
{
A a;
int i;
void set() { a.i = i = 42; }
};
std::ostream& operator<< (std::ostream& os, const B& b)
{ os <<'\t'<< b.a.i <<'\t'<< b.i; return os; }
int main()
{
std::cout <<"----------"<< __cplusplus <<"----------" "\n";
B b; // used to reset memory for 'placement new'
b.set(); std::cout <<"new(&b)B "<< *new(&b)B <<'\n'; // All uninitialized (in all C++ standards)
std::cout <<" B() "<< B() <<'\n'; // B::A::i uninitialized in C++03, zero-initialized in C++11
b.set(); std::cout <<"new(&b)B() "<< *new(&b)B() <<'\n'; // B::i zero-initialized (in all C++ standards)
#if __cplusplus > 2011*100 // B{} is aggregate-initialization (DR1301)
std::cout <<" B{} "<< B{} <<'\n'; // => B::A::i value-initialized
b.set(); std::cout <<"new(&b)B{} "<< *new(&b)B{} <<'\n'; // => B::i zero-initialized
#endif
}
构建输出和可能的 运行 输出
> clang++ --version
clang version 3.7.0 (tags/RELEASE_370/final 246979)
Target: x86_64-unknown-linux-gnu
Thread model: posix
> clang++ -std=c++03 -Wall -Wextra -pedantic main.cpp && ./a.out
----------199711----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
> clang++ -std=c++11 -Wall -Wextra -pedantic main.cpp && ./a.out
----------201103----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
B{} 4196348 0
new(&b)B{} 42 0
> clang++ -std=c++14 -Wall -Wextra -pedantic main.cpp && ./a.out
----------201402----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
B{} 4196348 0
new(&b)B{} 42 0
> clang++ -std=c++1z -Wall -Wextra -pedantic main.cpp && ./a.out
----------201406----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
B{} 4196348 0
new(&b)B{} 42 0
我正在玩C++ value initialization。
因此,我正在打印未初始化的值,以便根据 C++ 标准版本突出显示(未)初始化。
但是未初始化的值通常传达零值:-(
变量未初始化如何高亮?
(即,如何告诉编译器为未初始化的变量使用特定值?)
也许这可以使用 magic 用户提供的分配器来完成...
编辑: 我的以下代码片段不适用于生产。我只是想检查 C++ 标准关于 uninitialization/value-initialization/zero-initialization/default-initialization 机制的实现(通过编译器)。我不希望有关未初始化变量的编译器警告。我不想使用 MemoryCheckers。我只想强调编译器零初始化一些变量,默认初始化一些其他变量并且不初始化所有其他变量。并且这种初始化行为还取决于 C++ Standard 的版本。如果您认为最好的方法是使用编译器警告或 MemoryCheckers,请使用以下代码片段提供答案。
如果您已经理解我的问题,请不要阅读下面的详细尝试。
你可以build/run my first snippet on Coliru
#include <iostream>
struct A {
A() {} // user-defined default ctor does not initialize i
int i;
};
struct B {
A a;
};
int main()
{
std::cout << B().a.i << '\n';
// Results: C++03 -> uninitialized
// C++11 -> zero-initialized
std::cout << B{}.a.i << '\n';
// Results: C++03 -> Do not compile - B{} is correct since C++11
// C++11 -> uninitialized because
// DR1301 defines B{} as an aggregate-initialization
} // => A is value-initialized using the user-defined ctor
当使用 -std=c++03
编译时,执行可能会打印一个零值,但我更喜欢一个非零值。
0
使用-std=c++11
0
1208617840
另一个可能的输出使用-std=c++11
0
-201855824
但是 my more advanced snippet 现在未初始化对象的值为零 B{}.a.i
:-(
#include <iostream>
struct A {
A() {} // user-defined ctor does not initialize i
int i;
};
struct B {
A a;
};
int main()
{
std::cout <<"-----------"<< __cplusplus <<"-----------" "\n";
std::cout <<"B().a.i = "<< B().a.i <<'\n';
std::cout <<"B{}.a.i = "<< B{}.a.i <<'\n';
int d;
d = 42;
std::cout <<"(new(&d) B )->a.i = "<< (new(&d) B )->a.i <<'\n';
d = 42;
std::cout <<"(new(&d) B())->a.i = "<< (new(&d) B())->a.i <<'\n';
d = 42;
std::cout <<"(new(&d) B{})->a.i = "<< (new(&d) B{})->a.i <<'\n';
}
Build/Run 输出:
> g++ -std=c++03 -Wall -Wextra -pedantic main.cpp && ./a.out
-----------199711-----------
B().a.i = 0
(new(&d) B )->a.i = 42
(new(&d) B())->a.i = 0
> g++ -std=c++11 -Wall -Wextra -pedantic main.cpp && ./a.out
-----------201103-----------
B().a.i = 0
B{}.a.i = 0
(new(&d) B )->a.i = 42
(new(&d) B())->a.i = 0
(new(&d) B{})->a.i = 0
> g++ -std=c++14 -Wall -Wextra -pedantic main.cpp && ./a.out
-----------201402-----------
B().a.i = 0
B{}.a.i = 0
(new(&d) B )->a.i = 42
(new(&d) B())->a.i = 0
(new(&d) B{})->a.i = 0
一种可能的解决方案是使用 clang++
而不是 g++
。
clang++
v3.7 在我的特定情况下突出显示了未初始化的值。
注:此答案基于 C++ value initialization 自 C++11 以来已更改。值初始化是当 parentheses/braces 为空时: T(); T{}; new T(); new T{};
Build/Run Coliru
上的片段下方#include <iostream>
struct A
{
A() {} // ctor does not initialize 'i'
int i;
};
struct B // implicit ctor
{
A a;
int i;
void set() { a.i = i = 42; }
};
std::ostream& operator<< (std::ostream& os, const B& b)
{ os <<'\t'<< b.a.i <<'\t'<< b.i; return os; }
int main()
{
std::cout <<"----------"<< __cplusplus <<"----------" "\n";
B b; // used to reset memory for 'placement new'
b.set(); std::cout <<"new(&b)B "<< *new(&b)B <<'\n'; // All uninitialized (in all C++ standards)
std::cout <<" B() "<< B() <<'\n'; // B::A::i uninitialized in C++03, zero-initialized in C++11
b.set(); std::cout <<"new(&b)B() "<< *new(&b)B() <<'\n'; // B::i zero-initialized (in all C++ standards)
#if __cplusplus > 2011*100 // B{} is aggregate-initialization (DR1301)
std::cout <<" B{} "<< B{} <<'\n'; // => B::A::i value-initialized
b.set(); std::cout <<"new(&b)B{} "<< *new(&b)B{} <<'\n'; // => B::i zero-initialized
#endif
}
构建输出和可能的 运行 输出
> clang++ --version
clang version 3.7.0 (tags/RELEASE_370/final 246979)
Target: x86_64-unknown-linux-gnu
Thread model: posix
> clang++ -std=c++03 -Wall -Wextra -pedantic main.cpp && ./a.out
----------199711----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
> clang++ -std=c++11 -Wall -Wextra -pedantic main.cpp && ./a.out
----------201103----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
B{} 4196348 0
new(&b)B{} 42 0
> clang++ -std=c++14 -Wall -Wextra -pedantic main.cpp && ./a.out
----------201402----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
B{} 4196348 0
new(&b)B{} 42 0
> clang++ -std=c++1z -Wall -Wextra -pedantic main.cpp && ./a.out
----------201406----------
new(&b)B 42 42
B() 0 0
new(&b)B() 0 0
B{} 4196348 0
new(&b)B{} 42 0