静态常量标准::矢量



我正在用Qt编写一个图像查看器。我正在尝试在头文件中执行以下操作:

class ImageModel
{

private:
    const static std::vector<int> mZoomLevels;
}

在源文件中:

int zooms[] = {1,2,3,4,5,6,7,8,9,10};
const std::vector<int> mZoomLevels(zooms.begin(),zooms.end());

但是我收到以下错误:

在非类类型为"int[10]"的缩放中请求成员"开始" 请求非类类型"int[10]"的缩放中的成员"结束"

有谁知道如何初始化这个静态常量私有成员?

普通数组没有成员函数。我相信你正在寻找这个:

int zooms[] = {1,2,3,4,5,6,7,8,9,10};
const std::vector ImageModel::mZoomLevels(zooms, zooms + 10);

数组没有beginend成员。您可以将数组名称用于begin,将数组名称加长度用于末尾:

const std::vector mZoomLevels(zooms, zooms+10);

在 C++11 中,您可以使用 std::beginstd::end ,如下所示:

const std::vector mZoomLevels(std::begin(zooms), std::end(zooms));

在这两种情况下,最好将zooms数组文件声明为静态或将其隐藏在命名空间中,以确保其名称不会"污染"全局命名空间。

zooms 是一个没有成员和方法的 C 样式数组,即 zooms.beginzooms.end毫无意义。如果使用与 C++11 兼容的编译器,请尝试std::begin(zooms)std::end(zooms)

普通C++数组不能有成员。 但是,您正在寻找静态调度,这适用于按参数类型解析的重载。 因此,C++11 提供了std::beginstd::end非成员函数。 (这已经提到过了。

习惯调用非成员函数的最佳实践,如下所示(在编写通用模板代码时确实有帮助):

using std::begin;
using std::end;
const std::vector mZoomLevels(begin(zooms), end(zooms));

无论容器zooms是什么类型,这都可以正常工作,并且如果zooms具有某些自定义类类型,它将利用 ADL(依赖于参数的查找,有时称为 Koenig 查找)在同一命名空间中查找 beginend 的实现。

顺便说一句,std::beginstd::end 由 C++11 提供,但对于早期版本,您可以轻松编写自己的版本:

template <typename T, size_t N>
T* begin( T (&a)[N] ) { return a; }
template <typename T, size_t N>
T* end( T (&a)[N] ) { return a + N; }

我会在这里遵循不同的方法,具体取决于您是否可以访问 C++11。

在 C++03 中,我会使用一个普通数组(因为它是 const),甚至可能不在类中,而是在实现文件中的私有命名空间中(因为它是私有的,假设只有一个翻译单元具有 ImageModel 成员的定义)。

// cpp
namespace {
   static int gZoomLevels[] = { 1, 2, ... };
}

如果您真的想继续使用 std::vector<int> 方法,我会在翻译单元中创建一个定义成员的辅助函数并使用它来创建 std::vector ,而无需创建具有静态持续时间的不同变量:

namespace {
   static std::vector<int> chooseANameForInitializer() {
       int data[] = { 1, 2, 3 };
       return std::vector<int>( data, data + (sizeof data/sizeof *data) );
   }
}
const std::vector<int> ImageModel::mZoomLevels = chooseANameForInitializer();

在 C++11 中,我将改用std::array<int,...>,因为这避免了动态分配和额外间接寻址的成本。当然,这不是一个很大的收获,但是当您不需要它提供的任何功能时,拥有std::vector<int>是没有意义的。

class ImageModel
{
private:
    static const std::array<int,10> mZoomLevels;  
};
// cpp:
const std::array<int,10> ImageModel::mZoomLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

同样,如果您坚持使用std::vector<int>那么您可以使用列表初始化

const std::vector<int> ImageModel::mZoomLevels{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };

最新更新