首先:我知道大多数优化错误是由于编程错误或依赖于可能根据优化设置(浮点值,多线程问题......)而改变的事实.
然而,我经历了一个非常难以找到的错误,并且有些不确定是否有任何方法可以防止这些错误发生而不关闭优化.我错过了什么吗?这真的是一个优化器错误吗?这是一个简化的例子:
struct Data {
int a;
int b;
double c;
};
struct Test {
void optimizeMe();
Data m_data;
};
void Test::optimizeMe() {
Data * pData; // Note that this pointer is not initialized!
bool first = true;
for (int i = 0; i < 3; ++i) {
if (first) {
first = false;
pData = &m_data;
pData->a = i * 10;
pData->b = i * pData->a;
pData->c = pData->b / 2;
} else {
pData->a = ++i;
} // …Run Code Online (Sandbox Code Playgroud) 我有以下情况:我的问题围绕使用强类型枚举类作为标志(就像在C#中使用Flags-Attribute一样).我知道这不是枚举类首先使用的方式,但这不是这个问题的重点.
我已经定义了几个要在这些枚举类上使用的运算符和函数,以及一个自定义类型特征,用于区分常规枚举和Flag-enums.这是一个例子:
// Default type_trait which disables the following operators
template <typename T> struct is_flags : std::false_type {};
// Example operator to use enum class as flags
template <typename T>
std::enable_if_t<std::is_enum<T>::value && is_flags<T>::value, T&>
operator|=(T &t1, const T t2)
{
return t1 = static_cast<T>(static_cast<std::underlying_type_t<T>>(t1) |
static_cast<std::underlying_type_t<T>>(t2));
};
Run Code Online (Sandbox Code Playgroud)
现在如果我定义任何enum class我可以做以下事情:
enum class Foo { A = 1, B = 2 };
enum class Bar { A = 1, B = 2 };
// Declare "Bar" to be useable like …Run Code Online (Sandbox Code Playgroud) 我们正在挖掘一些非常古老的C++/CLI-Code(旧语法.NET Beta),看到类似的东西有点惊讶:
System::String ^source("Test-String");
printf("%s", source);
Run Code Online (Sandbox Code Playgroud)
程序正确输出
Test-String
Run Code Online (Sandbox Code Playgroud)
我们想知道,为什么可以将托管字符串源传递给printf- 更重要的是:为什么它可以工作?我不认为它是编译器的一些便利功能,因为以下不起作用:
System::String ^source("Test-String");
char pDest[256];
strcpy(pDest, source);
Run Code Online (Sandbox Code Playgroud)
这会产生(某种程度上预期的)编译错误,表示System::String^无法转换为const char*.因此,我唯一真正的解释是,将托管引用传递给va_list超过了所有编译器检查,并将本机代码用于使用指向托管堆的指针.由于在内存中System::String表示类似于char-Array,printf可能有效.或者编译器转换为a pin_ptr并将其传递给printf.
我不希望它自动编组String^to char*,因为这会导致内存泄漏,而不会引用实际的内存地址.
我们知道这不是一个好的解决方案,后来的Visual Studio-Versions引入的各种编组方法提供了一种更好的方法,但理解这里实际发生的事情会非常有趣.
谢谢!
是否有任何简单的机制可以使用 C++ 输入流(如ifstream)跳过直到下一个空格?
我知道ignore如果我知道要跳过多少个字符或需要什么分隔符,我就可以使用它。ignore但在我看来,当operator>>通常只是读取下一个空白而不提供任何其他参数时,使用起来很丑陋。我也可以使用假人,但这只会让事情变得更糟。
auto importantInfo1 = 0;
auto importantInfo2 = 0;
auto someDummy = 0; // This is ugly and doesn't clearly express the intent
file >> importantInfo1 >> someDummy >> importantInfo2;
Run Code Online (Sandbox Code Playgroud)
另外,在某些情况下,如果我需要在“跳过”情况下处理不同的数据类型,我将需要多个虚拟对象。
我会想象这样的事情:
file >> importantInfo1;
file.skip<int>(1);
file >> importantInfo2;
Run Code Online (Sandbox Code Playgroud)
或者甚至更好:
auto importantInfo1 = 0;
auto importantInfo2 = 0;
file >> importantInfo1 >> skip<int> >> importantInfo2;
Run Code Online (Sandbox Code Playgroud)
我想这样的解决方案也会比实际解析值并将其存储在不需要的地方更好。
使用提供的答案制定了此解决方案。与接受的答案基本相同,但不需要临时。相反,它会跳过第一个空格,然后跳过除空格之外的任何字符,直到再次到达空格为止。此解决方案可能使用 2 个 while 循环,但不需要了解提取的类型。我并不是说这是一个高性能解决方案或任何奇特的解决方案,但它使生成的代码更短、更干净且更具表现力。
template<typename CharT, typename Traits>
inline std::basic_istream<CharT, …Run Code Online (Sandbox Code Playgroud) 我已经找到了几个与转换std::time_t值相关的答案System::DateTime.但是,几乎所有答案似乎都忽略std::time_t了标准中实际上未定义的类型.大多数解决方案只是投射std::time_t到任何需要的或将算术运算应用于一个std::time_t可能的对象,因为它是一个算术类型,但是没有关于这种操作的结果的规范.我知道,大多数编译器定义time_t为int一些大小,但单独的事实,它已经从改变int32到int64在许多实现最近表明的变化的确是可能的.
所以我想出了这个解决方案,它应该与任何类型的工作std::time_t.它的工作原理我所看到的.但我想知道 - 我可能不知道有任何可能的陷阱吗?
template <>
inline System::DateTime marshal_as(const std::time_t &from_object)
{
// Returns DateTime in Local time format from time_t (assumed to be UTC)
const auto unix_epoch = makeUtcTime(1970, 1, 1, 0, 0, 0);
const auto unix_epoch_dt = System::DateTime(1970, 1, 1, 0, 0, 0, System::DateTimeKind::Utc);
const auto secondsSinceEpoch = std::difftime(from_object, unix_epoch);
return const_cast<System::DateTime&>(unix_epoch_dt).AddSeconds(secondsSinceEpoch).ToLocalTime();
} // …Run Code Online (Sandbox Code Playgroud) c++ ×3
.net ×2
c++-cli ×2
datetime ×1
enums ×1
flags ×1
istream ×1
marshalling ×1
mixed-mode ×1
optimization ×1
printf ×1
time-t ×1
type-traits ×1
visual-c++ ×1