静态内存分配 - 它是按顺序分配的吗?
Static memory allocation - is it allocated sequentially?
我需要知道是否保证对于所有编译器,以下代码中的 &N == &N_neg[MAXN]
。
int N_neg[MAXN], N[MAXN]; // defined in the global scope!
T<N> t; // so I can access N[i] (for i < 0) inside T
如果是这样,我就完成了,这就是我所需要的。 如果没有,请阅读下面我的完整问题。
注意:这仅用于编程竞赛,所以不用担心可维护性。我更关心如何让 T
易于理解。
我的定义如下:
template<int* B> class T { ... }
在 T
中,但是,我访问 B[-n]
,其中 n > 0
。所以,这就是我想要做的:
#define MAXN 1000
int N[2*MAXN];
T<N + MAXN> t;
根据编译器,这是不允许的。 cppreference 甚至有一个这种特殊情况的例子说它 不 工作,我已经在其他地方搜索了解决方案(none 尚未找到) .我确实了解模板的工作原理,并且我确实知道(以及为什么)每个模板参数的值必须在编译期间知道,而 N
的地址仅在稍后链接期间才知道。
有什么建议吗?
这是完整的代码(以防万一有人根据问题提出任何建议):
template<int M, int B[]> struct Hash {
int h; Hash(int h = 0): h(h) {}
int disp(int i) { return B[i]; }
Hash concat(int ch, int i) { return (h + (ll) ch * B[i]) % M; }
Hash subtract(int hl, int i) { return (ll) (h - hl + M) * B[-i] % M; }
static void genBase(int n, int b) {
B[0] = 1, B[-1] = powlg(b, M-2, M); // b^(-1) % M = b^(M-2) % M
for (int i = 1; i < n; i++)
B[i] = (ll) B[i-1] * b % M, B[-i] = (ll)B[-i+1] * B[-1] % M;
}
};
if it is guaranteed, for all compilers, that &N == &N_neg[MAXN]
绝对不能保证。 C++ 标准不强制变量的相对内存布局。事实上,它对内存布局的限制很少一般。
技术上什至不能保证 N
和 N_neg
在某些情况下不会被编译器优化掉(尽管获取它们的地址通常可以防止这种情况发生)。
要使布局顺序,可以使用结构:
struct { int N_neg[MAXN], N[MAXN]; } arrays;
然后,理论上您可以访问 N_neg[MAXN]
作为与 N[0]
相同的内存位置。然而,这是未定义的行为!它可以为你工作,但假设你分配给N_neg[MAXN]
。编译器可能会假设 N[0]
无法修改,并优化掉对它的任何访问,导致您的程序行为异常。
您可以通过声明两个数组 volatile
在某种程度上解决这个问题,但是您会失去大量潜在的优化。
因此,我会很不愿意使用这种方式。坚持定义的行为几乎总是更好。
根据 updated/discovered 要求,这使您 接近 只需要一个模板参数:
template <typename T, T&>
struct Hash;
template <std::size_t Size, typename T, T (&Array)[Size]>
struct Hash<T[Size], Array>
{
// Your code here
private:
static constexpr T *N = &Array[Size / 2];
};
像这样实例化:
int N_backing[MAXN * 2];
Hash<decltype(N_backing), N_backing> hash;
由于N
是constexpr
,它的值保证在编译时计算。
我需要知道是否保证对于所有编译器,以下代码中的 &N == &N_neg[MAXN]
。
int N_neg[MAXN], N[MAXN]; // defined in the global scope!
T<N> t; // so I can access N[i] (for i < 0) inside T
如果是这样,我就完成了,这就是我所需要的。 如果没有,请阅读下面我的完整问题。
注意:这仅用于编程竞赛,所以不用担心可维护性。我更关心如何让 T
易于理解。
我的定义如下:
template<int* B> class T { ... }
在 T
中,但是,我访问 B[-n]
,其中 n > 0
。所以,这就是我想要做的:
#define MAXN 1000
int N[2*MAXN];
T<N + MAXN> t;
根据编译器,这是不允许的。 cppreference 甚至有一个这种特殊情况的例子说它 不 工作,我已经在其他地方搜索了解决方案(none 尚未找到) .我确实了解模板的工作原理,并且我确实知道(以及为什么)每个模板参数的值必须在编译期间知道,而 N
的地址仅在稍后链接期间才知道。
有什么建议吗?
这是完整的代码(以防万一有人根据问题提出任何建议):
template<int M, int B[]> struct Hash {
int h; Hash(int h = 0): h(h) {}
int disp(int i) { return B[i]; }
Hash concat(int ch, int i) { return (h + (ll) ch * B[i]) % M; }
Hash subtract(int hl, int i) { return (ll) (h - hl + M) * B[-i] % M; }
static void genBase(int n, int b) {
B[0] = 1, B[-1] = powlg(b, M-2, M); // b^(-1) % M = b^(M-2) % M
for (int i = 1; i < n; i++)
B[i] = (ll) B[i-1] * b % M, B[-i] = (ll)B[-i+1] * B[-1] % M;
}
};
if it is guaranteed, for all compilers, that
&N == &N_neg[MAXN]
绝对不能保证。 C++ 标准不强制变量的相对内存布局。事实上,它对内存布局的限制很少一般。
技术上什至不能保证 N
和 N_neg
在某些情况下不会被编译器优化掉(尽管获取它们的地址通常可以防止这种情况发生)。
要使布局顺序,可以使用结构:
struct { int N_neg[MAXN], N[MAXN]; } arrays;
然后,理论上您可以访问 N_neg[MAXN]
作为与 N[0]
相同的内存位置。然而,这是未定义的行为!它可以为你工作,但假设你分配给N_neg[MAXN]
。编译器可能会假设 N[0]
无法修改,并优化掉对它的任何访问,导致您的程序行为异常。
您可以通过声明两个数组 volatile
在某种程度上解决这个问题,但是您会失去大量潜在的优化。
因此,我会很不愿意使用这种方式。坚持定义的行为几乎总是更好。
根据 updated/discovered 要求,这使您 接近 只需要一个模板参数:
template <typename T, T&>
struct Hash;
template <std::size_t Size, typename T, T (&Array)[Size]>
struct Hash<T[Size], Array>
{
// Your code here
private:
static constexpr T *N = &Array[Size / 2];
};
像这样实例化:
int N_backing[MAXN * 2];
Hash<decltype(N_backing), N_backing> hash;
由于N
是constexpr
,它的值保证在编译时计算。