C++ 17现在功能齐全,因此不太可能经历大的变化.为C++ 17提出了数百个提案.
在C++ 17中,哪些特性被添加到C++中?
当使用支持"C++ 1z"的C++编译器时,当编译器更新到C++ 17时,哪些功能可用?
假设我有一个带有可变数量参数的C函数:如何调用另一个函数,该函数需要从其内部获取可变数量的参数,并将所有参数传递到第一个函数中?
例:
void format_string(char *fmt, ...);
void debug_print(int dbg_lvl, char *fmt, ...) {
format_string(fmt, /* how do I pass all the arguments from '...'? */);
fprintf(stdout, fmt);
}
Run Code Online (Sandbox Code Playgroud) std::unique_ptr 支持数组,例如:
std::unique_ptr<int[]> p(new int[10]);
Run Code Online (Sandbox Code Playgroud)
但它需要吗?可能使用std::vector或更方便std::array.
你觉得这个结构有用吗?
什么是c ++ 20中的协同程序?
它与"Parallelism2"或/和"Concurrency2"的不同之处(见下图)?
以下图片来自ISOCPP.
在下面的代码中,我使用[[fallthrough]]C++ 1z中的标准属性来记录需要的漏洞:
#include <iostream>
int main() {
switch (0) {
case 0:
std::cout << "a\n";
[[fallthrough]]
case 1:
std::cout << "b\n";
break;
}
}
Run Code Online (Sandbox Code Playgroud)
使用GCC 7.1,代码编译时没有错误.但是,编译器仍然警告我一个问题:
warning: this statement may fall through [-Wimplicit-fallthrough=]
std::cout << "a\n";
~~~~~~~~~~^~~~~~~~
Run Code Online (Sandbox Code Playgroud)
为什么?
这是我在cpp.react库的文档中找到的C++代码段:
auto in = D::MakeVar(0);
auto op1 = in ->* [] (int in)
{
int result = in /* Costly operation #1 */;
return result;
};
Run Code Online (Sandbox Code Playgroud)
我从未见过这种->* []符号.首先,我认为这只是一个错字,但我也在源代码中找到了这样一个表达式:
auto volume = (width,height,depth) ->* [] (int w, int h, int d) {
return w * h * d;
};
Run Code Online (Sandbox Code Playgroud)
这是有效的C++ 11(或C++ 14)吗?这是什么意思?
在许多情况下,从函数返回局部时,RVO会启动.但是,我认为显式使用std::move至少会在RVO未发生时执行移动,但RVO仍然会在可能的情况下应用.但是,似乎情况并非如此.
#include "iostream"
class HeavyWeight
{
public:
HeavyWeight()
{
std::cout << "ctor" << std::endl;
}
HeavyWeight(const HeavyWeight& other)
{
std::cout << "copy" << std::endl;
}
HeavyWeight(HeavyWeight&& other)
{
std::cout << "move" << std::endl;
}
};
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return heavy;
}
int main()
{
auto heavy = MakeHeavy();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用VC++ 11和GCC 4.71,debug和release(-O2)配置测试了这段代码.永远不会调用复制文件.移动ctor仅在调试配置中由VC++ 11调用.实际上,特别是这些编译器似乎都很好,但据我所知,RVO是可选的.
但是,如果我明确使用move:
HeavyWeight MakeHeavy()
{
HeavyWeight heavy;
return std::move(heavy);
}
Run Code Online (Sandbox Code Playgroud)
移动ctor总是被称为.因此,试图使其"安全"会使情况变得更糟.
我的问题是:
- 为什么要std::move预防RVO?
- 何时更好地"希望最好"并依赖RVO,何时应该明确使用 …
考虑这两个功能:
void foo() {}
void bar() {}
Run Code Online (Sandbox Code Playgroud)
是保证&foo != &bar吗?
同样的,
template<class T> void foo() { }
Run Code Online (Sandbox Code Playgroud)
是保证&foo<int> != &foo<double>吗?
我知道折叠函数定义有两个连接器.
MSVC积极地COMDAT折叠函数,因此具有相同实现的两个函数可以转换为一个函数.作为副作用,这两个函数共享相同的地址.我的印象是这是非法的,但我无法找到标准中的哪些内容是非法的.
Gold链接器还可以折叠功能,包括a safe和all设置. safe意味着如果采用了一个功能地址,它就不会折叠,all即使采用了地址也会折叠.因此safe,如果函数具有不同的地址,则黄金的折叠表现为.
虽然折叠可能是意料之外的,并且存在依赖于具有不同地址的不同(相同实现)函数的代码(因此折叠可能是危险的),在当前的C++标准下它实际上是非法的吗?(此时为C++ 14)(自然如果safe折叠是合法的)
c++ function-pointers one-definition-rule language-lawyer comdat-folding
假设有一个std::array要初始化的东西.如果使用双括号可以:
std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};
Run Code Online (Sandbox Code Playgroud)
在良好的旧聚合初始化中使用单个括号也是可以的,因为括号省略将处理缺少的大括号:
std::array<int, 2> x = {0, 1};
Run Code Online (Sandbox Code Playgroud)
但是,使用单个括号的列表初始化是否可以?GCC接受它,Clang拒绝它"在使用直接列表初始化时不能省略关于子对象初始化的大括号".
std::array<int, 2> x{0, 1};
Run Code Online (Sandbox Code Playgroud)
提到括号内容的标准中唯一的部分是8.5.1/12,其中说:
使用赋值表达式初始化聚合成员时,将考虑所有隐式类型转换(第4节).如果赋值表达式可以初始化成员,则初始化成员.否则,如果成员本身是子集合,则假定使用大括号,并考虑赋值表达式初始化子集合的第一个成员.
8.5.1是关于聚合初始化的,所以应该意味着Clang是正确拒绝的,对吗?没那么快.8.5.4/3说:
列表初始化对象或类型T的引用定义如下:
[...]
- 否则,如果T是聚合,则执行聚合初始化(8.5.1).
我认为这意味着与聚合初始化完全相同的规则,包括括号elision,适用,意味着GCC是正确的接受.
我承认,措辞不是特别清楚.那么,哪个编译器正确处理第三个片段呢?括号省略是否在列表初始化中发生,或者不是?
c++ language-lawyer aggregate-initialization c++11 list-initialization