c++ - 如何强制编译器将非零值设置为未初始化的变量?

标签 c++ g++ clang++ compiler-options value-initialization

我正在玩 C++ value initialization .
因此,我正在打印未初始化的值,以便根据 C++ 标准版本突出显示(未)初始化。
但是未初始化的值通常传达零值:-(

如果一个变量没有被初始化,如何高亮显示?
(即,如何告诉编译器为未初始化的变量使用特定值?)

也许这可以使用用户提供的魔法分配器来完成...


编辑:我的以下代码片段不适用于生产。我只是想检查 C++ 标准关于未初始化/值初始化/零初始化/默认初始化机制的实现(由编译器)。我不希望有关未初始化变量的编译器警告。我不想使用 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';
}

构建/运行输出:

> 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 以来发生了变化。值初始化是在圆括号/大括号为空时:T(); T{};新 T();新 T{};

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++ - 如何强制编译器将非零值设置为未初始化的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33040013/

相关文章:

c++ - 对动态大小的对象进行排序

linux - 如何解决构建的.so文件出现undefined symbol错误?

c++ - 在位域 [dcl.enum] [class.bit] 中保存枚举类型

c++ - 类无法访问其自己的私有(private)静态 constexpr 方法 - Clang 错误?

c++ - Clang 3.8 C++ - 使用 LibTooling 读取目录中的所有源文件

c++ - Boost:两个工作线程,让主线程休眠直到它们都完成

c++ - 这个丑陋的构造函数/工厂有 C++ 惯用语吗?

c++ - 在 C++ 中创建新类型

c++ - 在 C++ 中删除结构 vector 中的重复值

c++ - 为什么当递归函数结果相乘时,g++仍然优化尾递归?