也许我不是来自这个星球,但在我看来,以下应该是语法错误:
int a[] = {1,2,}; //extra comma in the end
Run Code Online (Sandbox Code Playgroud)
但事实并非如此.我很惊讶,当编译这段代码在Visual Studio中,但我已经学会了不至于C++规则而言信任MSVC的编译器,所以我检查的标准,它是标准允许为好.如果你不相信我,你可以看到8.5.1的语法规则.
为什么允许这样做?这可能是一个愚蠢无用的问题,但我希望你理解我为什么这么问.如果它是一般语法规则的子案例,我会理解 - 他们决定不再使一般语法更难以在初始化列表的末尾禁止冗余逗号.但不,明确允许附加逗号.例如,在函数调用参数列表的末尾(当函数采用时...
)不允许使用冗余逗号,这是正常的.
那么,是否有任何特殊原因明确允许这个冗余逗号?
可以在头文件中写入以下内容:
inline void f () { std::function<void ()> func = [] {}; }
Run Code Online (Sandbox Code Playgroud)
要么
class C { std::function<void ()> func = [] {}; C () {} };
Run Code Online (Sandbox Code Playgroud)
我想在每个源文件中,lambda的类型可能不同,因此包含的类型std::function
(target_type
的结果会有所不同).
这是一个ODR(一个定义规则)违规,尽管看起来像一个共同的模式和合理的事情?第二个示例是每次都违反ODR还是仅在头文件中至少有一个构造函数?
来自http://en.cppreference.com/w/cpp/string/byte/memcpy:
如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为未定义.
在我的工作中,我们使用std::memcpy
了很长时间来按比例交换不是TriviallyCopyable的对象:
void swapMemory(Entity* ePtr1, Entity* ePtr2)
{
static const int size = sizeof(Entity);
char swapBuffer[size];
memcpy(swapBuffer, ePtr1, size);
memcpy(ePtr1, ePtr2, size);
memcpy(ePtr2, swapBuffer, size);
}
Run Code Online (Sandbox Code Playgroud)
从来没有任何问题.
我理解滥用std::memcpy
非TriviallyCopyable对象并导致下游的未定义行为是微不足道的.但是,我的问题是:
std::memcpy
当与非TriviallyCopyable对象一起使用时,为什么它本身的行为是未定义的?为什么标准认为有必要指定?
UPDATE
http://en.cppreference.com/w/cpp/string/byte/memcpy的内容已经过修改,以回应这篇文章和帖子的答案.目前的描述说:
如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为是未定义的,除非程序不依赖于目标对象(不运行
memcpy
)的析构函数的效果和生命周期目标对象(已结束,但未开始memcpy
)由其他一些方法启动,例如placement-new.
PS
@Cubbi的评论:
@RSahu如果有东西保证UB下游,它会使整个程序不确定.但我同意在这种情况下似乎可以绕过UB并相应地修改cppreference.
我有一个foo
可以抛出bar
异常的函数.
在我调用的另一个函数中,foo
但是bar
如果抛出,我可以向异常添加更多细节.(foo
由于该函数的通用特性,我宁愿不将这些信息作为参数传递给它,因为它并不真正属于那里.)
所以我在调用者中这样做:
try {
foo();
} catch (bar& ex){
ex.addSomeMoreInformation(...);
throw;
}
Run Code Online (Sandbox Code Playgroud)
会throw
重新抛出修改过的异常还是我需要使用throw ex;
?后者可能会采用有价值的副本,所以我宁愿不这样做.还会throw
带一个价值副本吗?我怀疑它不会.
(我知道我可以验证,但我担心绊倒一个未指定或未定义的构造,所以想知道肯定).
我想知道是否
std::is_unsigned<bool>::value
Run Code Online (Sandbox Code Playgroud)
根据标准是否明确定义?
我问这个问题因为typename std::make_unsigned<bool>::type
没有明确定义.
我经常使用一种技术,我称之为"懒人enable_if
",我使用它decltype
和逗号运算符来启用基于某些模板输入的函数.这是一个小例子:
template <typename F>
auto foo(F&& f) -> decltype(f(0), void())
{
std::cout << "1" << std::endl;
}
template <typename F>
auto foo(F&& f) -> decltype(f(0, 1), void())
{
std::cout << "2" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
随着--std=c++11
,g ++ 4.7+和Clang 3.5+愉快地编译那段代码(并且它按照我的预期工作).但是,当使用MSVC 14 CTP5时,我得到这个错误抱怨foo
已经定义:
错误错误C2995:'unknown-type foo(F &&)':函数模板已经定义了c ++ - scratch main.cpp 15
所以我的问题是:"懒人enable_if
"是合法的C++还是这是一个MSVC错误?
据我所知,override
关键字声明给定的声明实现了一个基本virtual
方法,如果找不到匹配的基本方法,编译应该失败.
我对该final
关键字的理解是它告诉编译器没有类会覆盖这个virtual
函数.
那是override final
多余的吗?好像编译好了.哪些信息override final
传达的final
不是?这种组合的用例是什么?
当clang编译以下行时,g ++ 6.1会抱怨数字分隔符(请参阅Coliru上的实例):
auto time = 01'23s;
Run Code Online (Sandbox Code Playgroud)
根据C++ 14标准(N3796),哪个编译器(如果有)是正确的?
否则,允许数字分隔符(§2.14.2)只是<chrono>
库的用户定义文字(§2.14.8)中的实现细节(§20.12.5.8)?恕我直言,它应该不是,因为这些文字是在unsigned long long
参数上定义的.
我记得Howard Hinnant10'000s
在他的CppCon 2016演讲"A <chrono>
tutorial"(在他的演讲中大约42分钟)中作为一个例子.
(请注意,我不打算编码"1分23秒",这只是偶然的,因为八进制文字0123是64 + 16 + 3 == 83.为此我应该写
auto time = 1min + 23s;
Run Code Online (Sandbox Code Playgroud)
但是这种可能误导性的解释不是问题的一部分.)
c++ language-lawyer user-defined-literals c++14 digit-separator
以下代码与GCC编译良好:
constexpr struct {} s;
Run Code Online (Sandbox Code Playgroud)
但Clang拒绝了它,出现以下错误:
错误:没有用户提供的默认构造函数,默认初始化const类型'const struct(anonymous struct at ...)'的对象
我已经测试了我能够在https://gcc.godbolt.org/找到的所有GCC和Clang版本.每个版本的GCC都接受代码,而Clang的每个版本都拒绝它.
我想知道在这种情况下哪个编译器是正确的?
标准对此有何看法?
当我使用g ++编译这个示例代码时,我收到此警告:
警告:解除引用类型惩罚指针将破坏严格别名规则
[-Wstrict-aliasing]
代码:
#include <iostream>
int main()
{
alignas(int) char data[sizeof(int)];
int *myInt = new (data) int;
*myInt = 34;
std::cout << *reinterpret_cast<int*>(data);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,不是data
别名int,因此将其强制转换为int不会违反严格的别名规则?或者我在这里遗漏了什么?
编辑:奇怪,当我这样定义时data
:
alignas(int) char* data = new char[sizeof(int)];
Run Code Online (Sandbox Code Playgroud)
编译器警告消失了.堆栈分配是否与严格别名产生差异?事实上它是一个char[]
而不是一个char*
意味着它实际上不能为任何类型别名吗?