Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以';常量指针不是常量表达式吗?_C++_Pointers_C++11_Constant Expression - Fatal编程技术网

C++ 为什么可以';常量指针不是常量表达式吗?

C++ 为什么可以';常量指针不是常量表达式吗?,c++,pointers,c++11,constant-expression,C++,Pointers,C++11,Constant Expression,以下程序编译: template <const int * P> class Test{}; extern const int var = 42; //extern needed to force external linkage int main() { Test<&var> test; } 我得出的结论是,指针不能是常量表达式,不管它是否为常量并用常量表达式初始化 问题: 我的结论是真的吗 如果是这样,为什么指针不能是常量表达式?如果没有,为什么

以下程序编译:

template <const int * P>
class Test{};

extern const int var = 42; //extern needed to force external linkage

int main()
{
    Test<&var> test;
}
我得出的结论是,指针不能是常量表达式,不管它是否为常量并用常量表达式初始化

问题:

  • 我的结论是真的吗
  • 如果是这样,为什么指针不能是常量表达式?如果没有,为什么上面的程序不编译
  • C++0x(C++11,如果你愿意的话)会改变什么吗

  • 谢谢你的见解

    在C++0x中仍然不允许这样做<代码>临时参数非类型要求:

    非类型、非模板参数的模板参数应为以下参数之一:

    • 对于整型或枚举型的非类型模板参数,模板参数类型的转换常量表达式(5.19);或
    • 非类型模板参数的名称;或
    • 一种常量表达式(5.19),用于指定具有静态存储持续时间和 外部或内部链接或具有外部或内部链接的功能,包括功能模板 和函数模板ID,但不包括非静态类成员,表示为(忽略括号)
      &
      id表达式
      ,但如果名称指函数或数组且应 如果对应的模板参数是引用,则省略;或
    • 计算为空指针值的常量表达式(4.10);或
    • 计算结果为空成员指针值的常量表达式(4.11);或
    • 指向构件的指针,如5.3.1所述

    原始答复:

  • 在C++03中,只有整数表达式可以是常量表达式
  • 因为标准是这样说的(自然)
  • 在C++0x中,n3290包括在指针上使用
    constexpr
    的示例。因此,您现在尝试的应该是可能的,尽管您现在必须使用
    constexpr
    关键字,而不是顶级
    const

  • <>也有GCC bug,

    < p>问题是因为你的C++程序可以在内存中的任何一个点加载,所以每次运行程序时,全局<代码> var >代码>的地址可能不同。如果运行两次程序会发生什么<代码>var显然位于两个不同的位置

    更糟糕的是,在您的示例中,您获取堆栈上变量的地址!看看这个:

    void myfunction( unsigned int depth) {
         const int myvar = depth;
         const int * const myptr = &myvar;
         if (depth)
             myfunction(depth-1);
    }
    
    如果main调用myfunction(3),那么将在不同的位置创建3个myvars。编译时甚至无法知道创建了多少MyVar,更不用说确切的位置了

    最后:将变量声明为
    const
    意味着:“我保证”,但这并不意味着它是编译时常量。请参见此示例:

    int main(int argc, char** argv) {
        const int cargc = argc;
        char* myargs[cargc]; //the size is constant, but not a _compile time_ constant.
    }
    

    这有点复杂。在C++03和C++11中,如果
    var
    是本地静态/类静态或命名空间范围变量,则
    &var
    是一个常量表达式。这称为地址常量表达式。使用该常量表达式初始化类静态或命名空间范围指针变量保证在运行任何代码之前完成(静态初始化阶段),因为它是一个常量表达式

    但是,只有在C++11之后,存储地址
    &var
    的constexpr指针变量也可以用作地址常量表达式,并且只有在C++11之后,您才能取消对地址常量表达式的引用(实际上,您可以取消对甚至更多的本地数组元素地址的引用,但让我们将其保留在桌面上)如果它指的是在取消引用之前初始化的常量整型变量或constexpr变量,则会再次得到常量表达式(取决于类型和值类别,常量表达式的类型可能会有所不同)。因此,以下内容在C++11中是有效的:

    int const x = 42;
    constexpr int const *px = &x;
    
    // both the value of "px" and the value of "*px" are prvalue constant expressions
    int array[*px];
    int main() { return sizeof(array); }
    
    如果是这样,为什么指针不能是常量表达式?如果没有,为什么上面的程序不编译


    这是标准措辞中的一个已知限制-对于指针类型的模板参数,它目前只允许其他模板参数作为参数或
    &object
    。尽管编译器应该能够做更多的工作。

    GCC给出了以下错误:“'ptr'不是有效的模板参数,因为'ptr'是一个变量,而不是变量的地址”这似乎表明指针模板参数必须是…地址的实际结果?@Kerrek SB:参见我的第二个示例-指针似乎不能是常量表达式。。。以某种方式然而,令人费解的是,GCC错误如何更加具体。这不仅仅是因为
    ptr
    不是一个常量表达式(实际上是),而是因为它是一个变量。不过,不知道该标准在哪里涵盖。@Kerrek SB:我怀疑它没有明确涵盖。这是我们应该推断的事情之一:)无论如何,我对为什么方面更感兴趣。我的意思是,很明显,指针的值是一个常量表达式,但指针本身不是。有什么障碍允许这样做?我实际上用
    constexpr
    尝试了所有这些,结果与我的其他评论中的结果相同……1)&var不是整数,是吗?2) 你的意思是“我不知道”@Kerrek SB的评论怎么样?@Kerrek:gcc没有在4.5.1中完全实现C++0x。你有更新的版本来测试吗?我正在用4.6.1进行测试。我们应该询问拥有快照版本的人,但错误消息似乎非常具体和故意,因此如果这只是错误地实现,我会感到惊讶。@Armen:我不认为
    &var
    在C++03中是一个常量表达式。实际的模板参数必须适合几个类别中的一个,常量表达式是一个,指针是另一个。C++0x合并了这些概念。我知道常量和常量表达式之间的区别。你的回答与本书结构合理的部分相矛盾
    int main(int argc, char** argv) {
        const int cargc = argc;
        char* myargs[cargc]; //the size is constant, but not a _compile time_ constant.
    }
    
    int const x = 42;
    constexpr int const *px = &x;
    
    // both the value of "px" and the value of "*px" are prvalue constant expressions
    int array[*px];
    int main() { return sizeof(array); }