我对C++的了解是不应该假设全局实例的构造(和析构)的顺序.
当我用编译器std::cout
和析构函数中使用的全局实例编写代码时,我遇到了一个问题.
std::cout
也是iostream的全局实例.是否std::cout
保证在任何其他全局实例之前进行初始化?
我写了一个简单的测试代码,它工作得很好,但我仍然不知道为什么.
#include <iostream>
struct test
{
test() { std::cout << "test::ctor" << std::endl; }
~test() { std::cout << "test::dtor" << std::endl; }
};
test t;
int main()
{
std::cout << "Hello world" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它打印
test::ctor
Hello world
test::dtor
Run Code Online (Sandbox Code Playgroud)
代码是否有可能无法按预期运行?
我正在尝试使用C++ 14的通用lambda,但是在使用std :: function时遇到了麻烦.
#include <iostream>
#include <functional>
int main()
{
const int a = 2;
std::function<void(int)> f = [&](auto b) { std::cout << a << ", " << b << std::endl; };
f(3);
}
Run Code Online (Sandbox Code Playgroud)
这无法编译,并显示错误消息error: ‘a’ was not declared in this scope
.
它可以工作,如果我改为(int b)
.
这是一个错误吗?还是我错过了什么?
我正在使用的GCC版本是4.9.2.
我听说noexcept
关键字更像是'它永远不应该抛出异常',而不是'它没有'.
我不认为使用noexcept
关键字是好的,如果我不确定它是否会抛出异常,但noexcept
关键字有时与移动构造函数中的性能有关.
所以我尝试使用noexcept
限定符,但如果它在定义中有多个语句就变得更难,它变成了一种复制和粘贴的东西.
template <class T>
void f(T&& t)
noexcept(noexcept(statement_1) &&
noexcept(statement_2) &&
noexcept(statement_3) &&
noexcept(statement_4) &&
noexcept(statement_5))
{
statement_1;
statement_2;
statement_3;
statement_4;
statement_5;
}
Run Code Online (Sandbox Code Playgroud)
我认为编译器可以判断一个函数的定义是否包含非抛出语句,因此noexcept
如果有一个类似的表达式会更容易使用noexcept(auto)
,但似乎标准中没有这样的东西.
有没有办法简化noexcept表达式?
我正在运行一个运行的线程,直到设置了一个标志.
std::atomic<bool> stop(false);
void f() {
while(!stop.load(std::memory_order_{relaxed,acquire})) {
do_the_job();
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道编译器是否可以像这样展开循环(我不希望它发生).
void f() {
while(!stop.load(std::memory_order_{relaxed,acquire})) {
do_the_job();
do_the_job();
do_the_job();
do_the_job();
... // unroll as many as the compiler wants
}
}
Run Code Online (Sandbox Code Playgroud)
据说波动率和原子性是正交的,但我有点困惑.编译器是否可以自由缓存原子变量的值并展开循环?如果编译器可以展开循环,那么我认为我必须加入volatile
标志,我想确定.
我应该放volatile
?
我很抱歉暧昧.我(我猜我)理解重新排序是什么memory_order_*
意思,我确定我完全理解它是什么volatile
.
我认为while()
循环可以转换为if
像这样的无限语句.
void f() {
if(stop.load(std::memory_order_{relaxed,acquire})) return;
do_the_job();
if(stop.load(std::memory_order_{relaxed,acquire})) return;
do_the_job();
if(stop.load(std::memory_order_{relaxed,acquire})) return;
do_the_job();
...
}
Run Code Online (Sandbox Code Playgroud)
由于给定的内存顺序不会阻止序列化之前的操作移过原子载荷,我认为如果没有易失性,它可以重新排列.
void f() {
if(stop.load(std::memory_order_{relaxed,acquire})) return;
if(stop.load(std::memory_order_{relaxed,acquire})) return;
if(stop.load(std::memory_order_{relaxed,acquire})) return;
...
do_the_job();
do_the_job();
do_the_job();
...
}
Run Code Online (Sandbox Code Playgroud)
如果原子并不意味着易失性,那么我认为在最坏的情况下代码甚至可以像这样转换.
void …
Run Code Online (Sandbox Code Playgroud) 除了链接相关的东西,我没有在标准中看到任何评论.
虽然标准没有说调用约定,但在现实世界中C和C++之间的调用约定可能不同,所以我期望C函数和C++函数的类型不同.但似乎没有,特别是在海湾合作委员会.
#include <type_traits>
extern "C" {
int c_func(int);
}
int cpp_func(int);
static_assert(!std::is_same<decltype(c_func), decltype(cpp_func)>::value,
"It should not be the same type");
Run Code Online (Sandbox Code Playgroud)
static_assert
由于GCC认为这些功能具有相同的类型,因此失败.
extern "C"
函数类型的一部分吗?我正在使用一个指向函数的数组.我编写了这样的代码,因为有些元素不能用函数模板表示.
extern void zero(); // isr 0 is defined somewhere else
void one() {
// isr 1
}
template <std::size_t N>
void Nth() {
// isr N
}
using func = void (*)();
constexpr func interrupt_vector[256] = {
&zero,
&one,
&Nth<2>,
&Nth<3>,
...
&Nth<254>,
&Nth<255>,
};
Run Code Online (Sandbox Code Playgroud)
我已经阅读过使用可变参数模板生成静态表,但那些是关于初始化整个数组的.
如何简化代码?
@实际上它是中断向量的一部分.由于它应该直接调用,我不能使用模板专业化,如
template <>
void Nth<0>() {
zero();
}
Run Code Online (Sandbox Code Playgroud)
@@编辑代码.我认为那些事情令人困惑.
我正在尝试使用CRTP实现编译时多态,并希望强制派生类实现该函数.
目前的实施是这样的.
template <class Derived>
struct base {
void f() {
static_cast<Derived*>(this)->f();
}
};
struct derived : base<derived>
{
void f() {
...
}
};
Run Code Online (Sandbox Code Playgroud)
在此实现中,如果派生类未实现,则对函数的调用将进入无限循环f()
.
如何强制派生类实现像纯虚函数一样的函数?我尝试使用'static_assert',static_assert(&base::f != &Derived::f, "...")
但它会生成一条错误消息,指出指向不同类的成员函数的两个成员函数指针不具有可比性.
我正在编写标准c ++库的实现用于研究.
C++ 11标准表示for_each
返回std::move(f)
.
template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
Returns: std::move(f).
Run Code Online (Sandbox Code Playgroud)
我认为函数范围局部变量在返回时是移动构造的.我应该move(f)
明确回来吗?
我正在用c ++ 11编写一个小内核,并且在创建任何其他静态对象之前必须构造两个具有相同类型的实例.
我写的代码如下:
// test.hpp
class test {
// blahblah...
};
// test.cpp
typedef char fake_inst[sizeof(test)] __attribute__((aligned(alignof(test))));
fake_inst inst1;
fake_inst inst2;
// main.cpp
extern test inst1;
extern test inst2;
int kmain() {
// copy data section
// initialize bss section
new (&inst1) test();
new (&inst2) test();
// call constructors in .init_array
// kernel stuffs
}
Run Code Online (Sandbox Code Playgroud)
它构建并按预期工作,没有任何警告消息,但LTO没有.
我收到大量的警告消息抱怨类型匹配,我想知道是否有一个解决方法,因为它让我困惑,找到其他"真正的"警告或错误消息.
有什么建议吗?
在下面的代码中,我认为断言不应该触发,但确实如此.
struct A
{
~A() noexcept(false);
};
A f() noexcept;
int main()
{
static_assert(noexcept(f()), "f must be noexcept");
}
Run Code Online (Sandbox Code Playgroud)
该函数f()
显然是noexcept,但noexcept(f())
被评估为false.(在gcc和clang中)
我错过了什么或者它是一个错误?