使用以下代码,我得到一个编译错误C2065 'a': undeclared identifier(使用Visual Studio 2017):
[] {
auto [a, b] = [] {return std::make_tuple(1, 2); }();
auto r = [&] {return a; }(); //error C2065
}();
Run Code Online (Sandbox Code Playgroud)
但是,以下代码编译:
[] {
int a, b;
std::tie(a, b) = [] {return std::make_tuple(1, 2); }();
auto r = [&] {return a; }();
}();
Run Code Online (Sandbox Code Playgroud)
我以为这两个样本是等价的.它是编译器错误还是我错过了什么?
在用基于范围的循环替换我的许多"旧"for循环之前,我使用visual studio 2013进行了一些测试:
std::vector<int> numbers;
for (int i = 0; i < 50; ++i) numbers.push_back(i);
int sum = 0;
//vectorization
for (auto number = numbers.begin(); number != numbers.end(); ++number) sum += *number;
//vectorization
for (auto number = numbers.begin(); number != numbers.end(); ++number) {
auto && ref = *number;
sum += ref;
}
//definition of range based for loops from http://en.cppreference.com/w/cpp/language/range-for
//vectorization
for (auto __begin = numbers.begin(),
__end = numbers.end();
__begin != __end; ++__begin) {
auto && ref = *__begin;
sum …Run Code Online (Sandbox Code Playgroud) 我被一个令人讨厌的"一个定义规则"违规所困扰.我现在害怕在我的项目中有很多微妙的错误.
例如,以下程序将导致使用visual studio 2015的空指针取消引用:
Source1.cpp:
----------
struct S {
double d = 0;
};
void Foo() {
S s;
}
Source2.cpp:
-----------
struct S {
int a = 0;
};
int main() {
int value = 5;
int& valueRef = value;
S s; // valueRef is erased due to S::d initialization from Source1.cpp
valueRef++; // crash
}
Run Code Online (Sandbox Code Playgroud)
编译时没有任何警告.
这是令人讨厌的,因为Source2.cpp甚至没有使用任何东西Source1.cpp.如果我Source1.cpp从项目中删除它仍然编译,并且没有问题了.
在大型项目中,似乎很难确保没有cpp文件"本地"定义具有已定义名称的结构或类.
我有一些类,如Point,Serie,State,Item,...我虽然这是小cpp文件确定,但我意识到这不是安全的.
是否有编译器警告来捕获此类错误?如果没有,避免ODR违规的最佳做法是什么?
我正在寻找快速SSE低精度(~1e-3)指数函数.
我遇到了这个很好的答案:
/* max. rel. error = 3.55959567e-2 on [-87.33654, 88.72283] */
__m128 FastExpSse (__m128 x)
{
__m128 a = _mm_set1_ps (12102203.0f); /* (1 << 23) / log(2) */
__m128i b = _mm_set1_epi32 (127 * (1 << 23) - 298765);
__m128i t = _mm_add_epi32 (_mm_cvtps_epi32 (_mm_mul_ps (a, x)), b);
return _mm_castsi128_ps (t);
}
Run Code Online (Sandbox Code Playgroud)
根据Nicol N. Schraudolph的工作:NN Schraudolph."指数函数的快速,紧凑近似." Neural Computation,11(4),1999年5月,pp.853-862.
现在我需要一个"双精度"版本:__m128d FastExpSSE (__m128d x).这是因为我不控制输入和输出精度,这恰好是双精度,并且两次转换double - > float,then float - > double占用了50%的CPU资源.
需要做哪些改变?
我天真地试过这个:
__m128i double_to_uint64(__m128d x) { …Run Code Online (Sandbox Code Playgroud) 我正在考虑使用 sse2 内在函数对一些 Floor() 调用进行矢量化,然后测量性能增益。但最终二进制文件将在我无法访问的虚拟机上运行。
我真的不知道虚拟机是如何工作的。二进制文件是否完全在软件模拟的虚拟 CPU 上执行?
如果不是,假设VM在具有SSE2的CPU上运行,那么当从我的二进制文件执行SSE2指令时,VM可以使用他的CPU SSE2指令吗?
我的矢量化对虚拟机有好处吗?
考虑这个例子:
#include <vector>
#include <stdexcept>
struct A
{
float a;
float b;
float c;
float d;
};
struct B
{
A a;
std::vector<int> b;
};
int main() {
B b{};
if (b.a.a || b.a.b || b.a.c || b.a.d) throw std::runtime_error("Compiler bug?");
}
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,根据https://en.cppreference.com/w/cpp/language/zero_initialization,它不能抛出,因为应该为 B::a 执行零初始化,因为它应该为“值初始化类的成员没有构造函数的类型”。
如果抛出,是编译器错误还是我遗漏了什么?
[编辑]
这里启用了 clang 10 和优化,它只执行“mov eax, 2”和“ret”(意味着条件为假):https : //godbolt.org/z/CXrc3G
但是如果我移除大括号,它会执行“mov eax, 1”和“ret”(意味着条件为真)。但在这里我认为它可以返回任何它想要的东西,因为它只是 UB。 https://godbolt.org/z/tBvLzZ
所以似乎clang认为必须使用大括号进行零初始化。
编辑:我在英特尔的网站上提交了一个错误:https : //community.intel.com/t5/Intel-C-Compiler/Aggregate-initialization-bug-with-nested-struct/td-p/1178228
一位情报人员回复“我已将此问题报告给我们的开发人员。” 可怜的开发者,一手支持所有的icc开发。
我正在处理新的 C++20 lambda,似乎我可以声明一个采用非类型模板参数的 lambda,但是我无法调用它。
#include <iostream>
int main() {
// compiles fine
auto f = []<bool ok>() { return ok; };
// it even has an address??
std::cout << &f;
// f(); // error : no matching function for call to object of typ
// f<true>(); // error : invalid operands to binary expression
f.operator()<true>(); // compiles but somewhat... ugly
}
Run Code Online (Sandbox Code Playgroud)
我在这里查看了相关论文,但似乎没有提到这种情况下的调用语法。
是否禁止在 lambda 调用站点显式传递模板参数?这将是一个令人失望的限制,因为我认为目的是让 lambda 能够像模板一样做很多事情。
我对此几乎感到满意:
const auto time = std::chrono::current_zone()->to_local(std::chrono::system_clock::now());
std::cout << time;
Run Code Online (Sandbox Code Playgroud)
它打印:
2023-07-26 21:08:47.2889025
Run Code Online (Sandbox Code Playgroud)
这很好,但我希望它打印的小数位数稍微少一些,例如:
2023-07-26 21:08:47.289
Run Code Online (Sandbox Code Playgroud)
是否有一些iomanip类似的方法来指定所需的精度?就像是:
std::cout << std::chrono::setprecision(3) << time;
Run Code Online (Sandbox Code Playgroud) 如果我的理解是正确的,
_mm_movehdup_ps(a)
给出与以下结果相同的结果
_mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 3, 3))?
两者在性能上有区别吗?
c++ ×8
c++20 ×2
lambda ×2
sse ×2
visual-c++ ×2
c++-chrono ×1
c++11 ×1
c++14 ×1
c++17 ×1
exponential ×1
intrinsics ×1
precision ×1
ranged-loops ×1
simd ×1
sse2 ×1
sse3 ×1
templates ×1
x86 ×1