相关疑难解决方法(0)

优化"while(1);" 在C++ 0x中

更新,见下文!

我听说并读过C++ 0x允许编译器为以下代码段打印"Hello"

#include <iostream>

int main() {
  while(1) 
    ;
  std::cout << "Hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

它显然与线程和优化功能有关.在我看来,这可能让许多人感到惊讶.

有人能够很好地解释为什么必须允许这样做吗?作为参考,最新的C++ 0x草案说明了6.5/5

在for语句的情况下,在for-init语句之外的循环,

  • 不调用库I/O函数,和
  • 不访问或修改易失性对象,以及
  • 不执行同步操作(1.10)或原子操作(第29条)

可以通过实现来假设终止.[注意:这是为了允许编译器转换,例如删除空循环,即使无法证明终止也是如此. - 结束说明]

编辑:

这篇富有洞察力的文章谈到了标准文本

不幸的是,没有使用"未定义的行为".但是,只要标准说"编译器可以假设P",就暗示具有非-P属性的程序具有未定义的语义.

这是正确的,是否允许编译器为上述程序打印"Bye"?


这里有一个更有见地的线索,这是关于C的类似改变,由Guy完成上述链接文章开始.在其他有用的事实中,他们提出了一个似乎也适用于C++ 0x的解决方案(更新:这将不再适用于n3225 - 见下文!)

endless:
  goto endless;
Run Code Online (Sandbox Code Playgroud)

看来,编译器不允许优化它,因为它不是循环,而是跳转.另一个人总结了C++ 0x和C201X的建议更改

通过编写一个循环,程序员断言或者环路不可见的东西的行为(执行I/O,访问volatile对象,或执行同步或原子操作), 或者,它最终会终止.如果我通过编写一个没有副作用的无限循环来违反这个假设,我对编译器撒谎,而我的程序的行为是未定义的.(如果我很幸运,编译器可能会警告我.)语言不提供(不再提供?)表达无可见行为的无限循环的方法.


2011年3月3日更新为n3225:委员会将案文移至1.10/24并说

实现可以假定任何线程最终将执行以下操作之一:

  • 终止,
  • 调用库I/O函数,
  • 访问或修改易失性对象,或
  • 执行同步操作或原子操作.

goto把戏,工作了!

c++ optimization loops c++11

150
推荐指数
5
解决办法
1万
查看次数

std :: move是否真的需要在构造函数的初始化列表中通过值传递的重成员?

最近我从cppreference中读到了一个例子.../vector/emplace_back:

struct President
{
    std::string name;
    std::string country;
    int year;

    President(std::string p_name, std::string p_country, int p_year)
        : name(std::move(p_name)), country(std::move(p_country)), year(p_year)
    {
        std::cout << "I am being constructed.\n";
    }
Run Code Online (Sandbox Code Playgroud)

我的问题:这std::move真的需要吗?我的观点是,这p_name不是在构造函数体中使用,所以,也许,语言中有一些规则默认使用移动语义?

将std :: move初始化列表添加到每个重要成员(例如std::string,std::vector)会非常烦人.想象一下用C++ 03编写的数百个KLOC项目 - 我们是否应该添加到处std::move

这个问题:move-constructor-and-initialization-list答案说:

作为一个黄金法则,无论何时你通过右值引用来获取内容,你需要在std :: move中使用它,并且每当你通过通用引用(即用&&推导出模板化类型)时,你需要在std ::里面使用它向前

但我不确定:通过价值而不是普遍的参考?

[UPDATE]

使我的问题更清楚.构造函数参数可以被视为XValue - 我的意思是到期值?

在这个例子AFAIK我们不使用std::move:

std::string getName()
{
   std::string local = "Hello SO!";
   return local; // std::move(local) is not needed nor …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer initialization-list move-semantics c++11

34
推荐指数
3
解决办法
7321
查看次数

Clang真的很聪明吗?

如果我使用Clang 3.3编译以下代码,-O3 -fno-vectorize即使删除了注释行,也会得到相同的汇编输出.代码类型将所有可能的32位整数置于浮点数并计算[0,1]范围内的值.Clang的优化器实际上是否足够聪明,以致当被处理为浮点数时0xFFFFFFFF不在[0,1]的范围内,所以忽略fn完全的第二次调用?删除第二个调用时,GCC会生成不同的代码.

#include <limits>
#include <cstring>
#include <cstdint>

template <class TO, class FROM>
inline TO punning_cast(const FROM &input)
{
    TO out;
    std::memcpy(&out, &input, sizeof(TO));
    return out;
}

int main()
{
    uint32_t count = 0;

    auto fn = [&count] (uint32_t x) {
        float f = punning_cast<float>(x);
        if (f >= 0.0f && f <= 1.0f)
            count++;
    };

    for(uint32_t i = 0; i < std::numeric_limits<uint32_t>::max(); ++i)
    {
        fn(i);
    }
    fn(std::numeric_limits<uint32_t>::max()); //removing this changes nothing

    return count;
}
Run Code Online (Sandbox Code Playgroud)

见这里: …

c++ llvm clang compiler-optimization c++11

8
推荐指数
1
解决办法
614
查看次数