构建一个'长期'

Zer*_*ero 5 gcc

你如何构建一个long longgcc,类似于构建一个intviaint()

gcc中的以下内容失败(4.6.3 20120306)(但以MSVC为例).

myFunctionCall(someValue, long long());
Run Code Online (Sandbox Code Playgroud)

有错误expected primary-expression before 'long'(列位置表示第一个长度是位置).

一个简单的改变

myFunctionCall(someValue, (long long)int());
Run Code Online (Sandbox Code Playgroud)

工作得很好 - 这是构造一个int并转换为long long- 表明gcc不喜欢long longctor.

摘要解决方案

总结下面@birryree的精彩解释:

  • 许多编译器不支持long long(),可能不符合标准
  • 构造long long等同于文字0LL,所以使用myFunctionCall(someValue, 0LL)
  • 可替换地使用typedef long_long_t long long,然后long_long_t()
  • 最后,可以考虑使用uint64_t ,如果你是一个类型,它是在任何平台上正好是64位,而不是一个类型,它是在经过至少 64位,但可以在不同的平台而有所不同.

wkl*_*wkl 5

我希望得到一个关于预期行为的明确答案,所以我发布了一个问题comp.lang.c++.moderated并获得了一些很好的答案. 感谢Johannes Schaub,Alf P. Steinbach(均来自SO)和Francis Glassborrow的一些信息.

这不是GCC中的错误 - 实际上它会突破多个编译器 - GCC 4.6,GCC 4.7和Clang抱怨类似的错误,primary expression expected before '('如果你尝试这种语法:

long long x = long long();
Run Code Online (Sandbox Code Playgroud)

一些原语有空格,如果你想使用构造函数式初始化因为绑定(long()绑定,但long long()有一个空闲long),则不允许这样做.其中包含空格的类型(如long long)不能使用type()-construction表单.

MSVC在这里更宽松,虽然技术上非标准兼容(并且它不是你可以禁用的语言扩展).

解决方案/解决方法

您可以选择其他方式:

  • 使用0LL到位试图为你的价值long long()-他们会产生相同的值.

    这也是大多数代码的编写方式,因此对于阅读代码的其他人来说,这是最容易理解的.

  • 从你的评论看起来你真的想要long long,所以你可以typedef自己总是保证你有一个long long类型,如下所示:

    int main() {
        typedef long long MyLongLong;
        long long x = MyLongLong(); // or MyLongLong x = MyLongLong();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用模板来解决需要显式命名的问题:

    template<typename TypeT>
    struct Type { typedef TypeT T(); };
    
    // call it like this:
    long long ll = Type<long long>::T();
    
    Run Code Online (Sandbox Code Playgroud)
  • 正如我在评论中提到的,您可以使用别名类型,例如int64_t(from <cstdint>),它跨越常见平台typedef long long int64_t.这比此列表中的先前项目更依赖于平台.

    int64_t是64位的固定宽度类型,通常long long在linux-x86和windows-x86等平台上有多宽.long long至少是64位宽,但可以更长.如果您的代码只能在某些平台上运行,或者您确实需要固定宽度类型,那么这可能是一个可行的选择.

C++ 11解决方案

感谢C++新闻组,我学到了一些其他方法来做你想做的事情,但遗憾的是它们只是在C++ 11领域(并且MSVC10也不支持,而且只有非常新的编译器才会):


那么POD类型()和初始化之间是否存在真正的区别0

你在评论中这样说:

我不认为默认ctor总是返回零 - 更典型的行为是保持内存不变.

那么,对于原始类型,这根本不是真的.

第8.5节ISO C++标准/ 2003(没有2011,抱歉,但这些信息并没有改变太多):

默认初始化类型对象T意味着:

- 如果T是非POD类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);

- 如果T是数组类型,则每个元素都是默认初始化的;

- 否则,对象被零初始化.

最后一句话,是这里最重要的是因为long long,unsigned long,int,float,等都是标/ POD类型,所以调用这样的事情:

int x = int();
Run Code Online (Sandbox Code Playgroud)

这样做完全相同:

int x = 0;
Run Code Online (Sandbox Code Playgroud)

生成的代码示例

以下是代码中实际发生的更具体的示例:

#include <iostream>

template<typename T>
void create_and_print() {
   T y = T();
   std::cout << y << std::endl;
}

int main() {
   create_and_print<unsigned long long>();

   typedef long long mll;
   long long y = mll();
   long long z = 0LL;

   int mi = int();
}
Run Code Online (Sandbox Code Playgroud)

用以下内容编译:

g++ -fdump-tree-original construction.cxx
Run Code Online (Sandbox Code Playgroud)

我在生成的树转储中得到了这个:

;; Function int main() (null)
;; enabled by -tree-original

{
  typedef mll mll;
  long long int y = 0;
  long long int z = 0;
  int mi = 0;

  <<cleanup_point <<< Unknown tree: expr_stmt
  create_and_print<long long unsigned int> () >>>>>;
  <<cleanup_point   long long int y = 0;>>;
  <<cleanup_point   long long int z = 0;>>;
  <<cleanup_point   int mi = 0;>>;
}
return <retval> = 0;



;; Function void create_and_print() [with T = long long unsigned int] (null)
;; enabled by -tree-original

{
  long long unsigned int y = 0;

  <<cleanup_point   long long unsigned int y = 0;>>;
  <<cleanup_point <<< Unknown tree: expr_stmt
  (void) std::basic_ostream<char>::operator<< ((struct __ostream_type *) std::basic_ostream<char>::operator<< (&cout, y), endl) >>>>>;
}
Run Code Online (Sandbox Code Playgroud)

生成的代码含义

因此,从上面生成的代码树中,注意我的所有变量都只是初始化0,即使我使用构造函数样式的默认初始化,就像使用int mi = int().GCC将生成恰好的代码int mi = 0.

我的模板函数只是尝试做一些传入的默认构造typename T,其中T = unsigned long long,也产生了一个0初始化代码.


结论

总而言之,如果你想默认构造原始类型/ POD,就像使用它一样0.