首页 > 解决方案 > C++ constexpr 构造函数初始化垃圾值

问题描述

我想要一个简单的类,它可以封装一个指针和一个大小,就像 C++20 那样std::span,我想。我正在使用 C++(准确地说是 g++ 11.2.1)

我想要它,这样我就可以拥有一些恒定的模块级数据数组,而不必计算每个数组的大小。

但是,我的实现仅在某些时候“有效”,这取决于优化标志和编译器(我在 Godbolt 上尝试过)。因此,我犯了一个错误。我该如何正确地做到这一点?

这是实现加上一个测试程序,它打印出元素的数量(总是正确的)和元素(通常是错误的)

#include <iostream>
#include <algorithm>
using std::cout;
using std::endl;

class CArray {
 public:
  template <size_t S>
  constexpr CArray(const int (&e)[S]) : els(&e[0]), sz(S) {}
  const int* begin() const { return els; }
  const int* end() const { return els + sz; }
private:
  const int* els;
  size_t sz;
};
const CArray gbl_arr{{3,2,1}};

int main() {
  CArray arr{{1,2,3}};
  cout << "Global size: " << std::distance(gbl_arr.begin(), gbl_arr.end()) << endl;
  for (auto i : gbl_arr) {
    cout << i << endl;
  }
  cout << "Local size: " << std::distance(arr.begin(), arr.end()) << endl;
  for (auto i : arr) {
    cout << i << endl;
  }
  return 0;
}

样本输出:

Global size: 3
32765
0
0
Local size: 3
1
2
3

在这种情况下,“局部”变量是正确的,但“全局”不是,应该是 3,2,1。

标签: c++c++17

解决方案


我认为问题在于您的初始化正在创建一个临时对象,然后在该数组被销毁后存储一个指向该数组的指针。

const CArray gbl_arr{{3,2,1}};

调用上述构造函数时,传入的参数仅为调用本身创建,但 gbl_arr 在其生命周期结束后引用它。改成这样:

int gbl_arrdata[]{3,2,1};
const CArray gbl_arr{gbl_arrdaya};

它应该可以工作,因为它引用的数组现在与引用它的对象具有相同的生命周期范围。


推荐阅读