你如何构建一个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位,但可以在不同的平台而有所不同.我希望得到一个关于预期行为的明确答案,所以我发布了一个问题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++新闻组,我学到了一些其他方法来做你想做的事情,但遗憾的是它们只是在C++ 11领域(并且MSVC10也不支持,而且只有非常新的编译器才会):
该{}方式:
long long ll{}; // does the zero initialization
Run Code Online (Sandbox Code Playgroud)使用Johannes所说的C++ 11中的'bord工具' std::common_type<T>
#include <type_traits>
int main() {
long long ll = std::common_type<long long>::type();
}
Run Code Online (Sandbox Code Playgroud)()和初始化之间是否存在真正的区别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.