只要我有一个包含声明为void g(void (*callback)());
的函数的C库以下代码是优雅但非法的:
struct A
{
// error C2159: more than one storage class specified (VC++ Nov 2012 CTP)
static extern "C" void callback()
{}
};
g(A::callback);
Run Code Online (Sandbox Code Playgroud)
为什么C++ 11不支持这个?
C和C++标准支持信号的概念.但是,C11标准表示无法在多线程环境中调用函数signal(),或者行为未定义.但我认为信号机制本质上适用于多线程环境.
引用C11标准7.14.1.1.7
"在多线程程序中使用此函数会导致未定义的行为.实现的行为就像没有库函数调用信号函数一样."
对此有何解释?
以下代码不言而喻.
#include <thread>
#include <csignal>
using namespace std;
void SignalHandler(int)
{
// Which thread context here?
}
void f()
{
//
// Running in another thread context.
//
raise(SIGINT); // Is this call safe?
}
int main()
{
//
// Register the signal handler in main thread context.
//
signal(SIGINT, SignalHandler);
thread(f).join();
}
Run Code Online (Sandbox Code Playgroud) #include <thread>
#include <string>
#include <vector>
#include <chrono>
using namespace std;
void f(const vector<string>& coll)
{
this_thread::sleep_for(1h);
//
// Is coll guaranteed to be valid before exiting this function?
//
}
int main()
{
{
vector<string> coll(1024 * 1024 * 100);
thread(f, coll).detach();
}
//
// I know std::thread will copy arguments into itself by default,
// but I don't know whether these copied objects are still valid
// after the std::thread object has been destroyed.
//
while (true);
} …
Run Code Online (Sandbox Code Playgroud) 在C++ 11中,以下两个语句都是合法的:
声明1. int a[8] = {};
声明2. int a[8]{};
但是,我更喜欢声明1而不是声明2因为我认为声明1更具表现力.
C++ 11标准是否保证两个语句在语义上是等效的?
#include <vector>
int main()
{
auto v = std::vector{std::vector<int>{}};
return v.front().empty(); // error
}
Run Code Online (Sandbox Code Playgroud)
看在线演示
然而,根据 Scott Meyers 的Effective Modern C++(强调原文):
但是,如果一个或多个构造函数声明了一个类型为 的参数
std::initializer_list
,则使用花括号初始化语法的调用强烈倾向于采用 的重载std::initializer_lists
。强烈。如果编译器有任何方法可以将使用花括号初始化器的调用解释为采用 a 的构造函数std::initializer_list
,则编译器将采用该解释。
所以,我认为std::vector{std::vector<int>{}};
应该产生一个对象std::vector<std::vector<int>>
而不是std::vector<int>
.
谁错了?为什么?
我搜索了互联网,发现了很多关于这个主题的文章.但是,我发现没有完整的清单来验证我们的代码的异常安全质量.
所以,我想从你那里收集有价值的C++异常处理最佳实践.
我首先列出了我自己的一些做法:
在析构函数中捕获所有异常:
struct A
{
~A()
{
try
{
// Here may throw exceptions
}
catch (std::runtime_error& e)
{}
catch (...)
{
logging("...");
}
}
};
Run Code Online (Sandbox Code Playgroud)在异常信息中添加函数名,源文件名和行数.__func__
,__FILE__
并且__LINE__
是好朋友.
切勿使用例外规格.原因在"C++编码标准"一书中给出.
你的是什么?
众所周知,在大多数情况下,T&&
意味着"这是一个临时对象".但是,如果想要从函数返回临时对象,他/她可以按如下方式声明函数:
template<class T>
T f()
{
T t;
......
return t;
}
Run Code Online (Sandbox Code Playgroud)
或(注意:不正确)
template<class T>
T&& f()
{
T t;
......
return t;
}
Run Code Online (Sandbox Code Playgroud)
但我认为后者是过度的,因为前者足够向后兼容.
然而,我也发现它std::forward()
的返回类型被声明为T &&,所以我确信我对此的理解是不完整的.
我真正的问题是:我们何时何地将函数的返回类型声明为T &&?
struct A
{
// error C2216: 'explicit' cannot be used with 'virtual'
virtual explicit operator bool() const
{
return true;
}
};
struct B : A
{
// error C2216: 'explicit' cannot be used with 'override'
explicit operator bool() const override
{
return false;
}
};
int main()
{
if (A())
{}
if (B())
{}
}
Run Code Online (Sandbox Code Playgroud)
我的编译器是VC++ 2013 RC.
为什么explicit
不兼容virtual
?
理由是什么?
cppref已删除了入口页面std::is_callable
,并std::is_invocable
改为使用入口页面.
但是,std::is_callable
仍可在Visual Studio 2017中使用.
被std::is_callable
正式[ 取出更换| |不赞成用] std::is_invocable
在C++ 17?
struct X { int a, b; };
int main()
{
auto p = std::pair{ 1, 2 };
const auto&[r1, r2] = p; // ok
X x{ 1, 2 };
const auto&[r3, r4] = x; // error
}
Run Code Online (Sandbox Code Playgroud)
clang 7.0(在Windows上)的错误信息:
error : cannot decompose this type; 'std::tuple_size<const X>::value' is not a valid
integral constant expression
Run Code Online (Sandbox Code Playgroud)
为什么结构化绑定在struct上不能按预期工作?
c++ ×10
c++11 ×7
standards ×4
c++17 ×3
c ×2
alias ×1
coding-style ×1
ctad ×1
exception ×1
explicit ×1
extern ×1
function ×1
logging ×1
performance ×1
return-type ×1
signals ×1
static ×1
temporary ×1
type-traits ×1
virtual ×1