标签: language-lawyer

从理论上讲,C++实现可以并行化两个函数参数的评估吗?

给出以下函数调用:

f(g(), h())
Run Code Online (Sandbox Code Playgroud)

因为函数参数的计算顺序是不确定的(仍然是在C++ 11,据我所知的情况下),可以实现理论上执行g()h()并行?

这种并行化只能起作用g并且h已知是相当微不足道的(在最明显的情况下,仅访问其本体的本地数据)以便不引入并发性问题但是,除了该限制之外,我看不到任何禁止它的内容.

那么,标准是否允许它?即使只是按照as-if规则?

(在这个答案中,Mankarse声称不然;但是,他没有引用标准,而我的通读[expr.call]并没有透露任何明显的措辞.)

c++ language-lawyer

68
推荐指数
2
解决办法
2388
查看次数

可以在头文件中使用lambda违反ODR吗?

可以在头文件中写入以下内容:

inline void f () { std::function<void ()> func = [] {}; }
Run Code Online (Sandbox Code Playgroud)

要么

class C { std::function<void ()> func = [] {}; C () {} };
Run Code Online (Sandbox Code Playgroud)

我想在每个源文件中,lambda的类型可能不同,因此包含的类型std::function(target_type的结果会有所不同).

这是一个ODR(一个定义规则)违规,尽管看起来像一个共同的模式和合理的事情?第二个示例是每次都违反ODR还是仅在头文件中至少有一个构造函数?

c++ lambda one-definition-rule language-lawyer c++11

68
推荐指数
2
解决办法
4182
查看次数

为什么在Python中使用双分号作为SyntaxError?

我知道Python中不需要分号,但它们可以用于将多个语句塞入一行,例如

>>> x = 42; y = 54
Run Code Online (Sandbox Code Playgroud)

我一直认为分号相当于换行符.所以我有点惊讶(在推特上没有Ned Batchelder)双分号是一个SyntaxError:

>>> x = 42
>>> x = 42;
>>> x = 42;;
  File "<stdin>", line 1
    x = 42;;
           ^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

我假设最后一个程序相当于x = 42\n\n.我以为分号之间的陈述被视为一个空行,一个无操作.显然不是.

为什么这是一个错误?

python syntax-error language-lawyer

68
推荐指数
2
解决办法
3381
查看次数

为什么对于非TriviallyCopyable的对象,未定义std :: memcpy的行为?

来自http://en.cppreference.com/w/cpp/string/byte/memcpy:

如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为未定义.

在我的工作中,我们使用std::memcpy了很长时间来按比例交换不是TriviallyCopyable的对象:

void swapMemory(Entity* ePtr1, Entity* ePtr2)
{
   static const int size = sizeof(Entity); 
   char swapBuffer[size];

   memcpy(swapBuffer, ePtr1, size);
   memcpy(ePtr1, ePtr2, size);
   memcpy(ePtr2, swapBuffer, size);
}
Run Code Online (Sandbox Code Playgroud)

从来没有任何问题.

我理解滥用std::memcpy非TriviallyCopyable对象并导致下游的未定义行为是微不足道的.但是,我的问题是:

std::memcpy当与非TriviallyCopyable对象一起使用时,为什么它本身的行为是未定义的?为什么标准认为有必要指定?

UPDATE

http://en.cppreference.com/w/cpp/string/byte/memcpy的内容已经过修改,以回应这篇文章和帖子的答案.目前的描述说:

如果对象不是TriviallyCopyable(例如标量,数组,C兼容结构),则行为是未定义的,除非程序不依赖于目标对象(不运行memcpy)的析构函数的效果和生命周期目标对象(已结束,但未开始memcpy)由其他一些方法启动,例如placement-new.

PS

@Cubbi的评论:

@RSahu如果有东西保证UB下游,它会使整个程序不确定.但我同意在这种情况下似乎可以绕过UB并相应​​地修改cppreference.

c++ memcpy object-lifetime language-lawyer c++11

67
推荐指数
5
解决办法
5355
查看次数

De Morgan的Law优化与重载运算符

每个程序员都应该知道:

德摩根1
德摩根2
(德摩根定律)

在某些情况下,为了优化程序,编译器可能会修改(!p && !q)(!(p || q)).

这两个表达式是等价的,并且评估第一个或第二个没有区别.
但是在C++中,可能会重载运算符,而重载的运算符可能并不总是尊重这个属性.因此,以这种方式转换代码实际上将修改代码.

如果编译器使用德摩根定律时!,||&&超载?

c++ operator-overloading compiler-optimization language-lawyer

67
推荐指数
4
解决办法
3654
查看次数

可能是sizeof(T*)!= sizeof(const T*)的情况?

我正和我的老板争论这件事.他们说"是的,他们可以是不同的."

有可能是sizeof(T*) != sizeof(const T*)一种类型T

c++ language-lawyer

67
推荐指数
3
解决办法
3316
查看次数

在C++函数中"返回"的确切时刻

这似乎是一个愚蠢的问题,但是return xxx;在一个明确定义的函数中"执行" 的确切时刻?

请参阅以下示例以了解我的意思(现在直播):

#include <iostream>
#include <string>
#include <utility>

//changes the value of the underlying buffer
//when destructed
class Writer{
public:
    std::string &s;
    Writer(std::string &s_):s(s_){}
    ~Writer(){
        s+="B";
    }
};

std::string make_string_ok(){
    std::string res("A");
    Writer w(res);
    return res;
}


int main() {
    std::cout<<make_string_ok()<<std::endl;
} 
Run Code Online (Sandbox Code Playgroud)

我天真地期待发生的事情make_string_ok被称为:

  1. 构造函数res被调用(价值res就是"A")
  2. w调用构造函数
  3. return res被执行.应该返回res的当前值(通过复制当前值res),即"A".
  4. w被称为析构函数,值res变为"AB".
  5. 析构res函数被称为.

所以我希望"A"结果,但"AB" …

c++ object-lifetime language-lawyer copy-elision c++17

67
推荐指数
3
解决办法
4121
查看次数

是否允许编译器优化堆内存分配?

考虑以下使用的简单代码new(我知道没有delete[],但它与此问题无关):

int main()
{
    int* mem = new int[100];

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

是否允许编译器优化new呼叫?

在我的研究中,g ++(5.2.0)和Visual Studio 2015不会优化new呼叫,而clang(3.0+)则可以.所有测试都是在启用完全优化的情况下进行的(-O3用于g ++和clang,用于Visual Studio的发布模式).

是不是new在引擎盖下进行系统调用,使编译器无法(并且非法)优化它?

编辑:我现在已经从程序中排除了未定义的行为:

#include <new>  

int main()
{
    int* mem = new (std::nothrow) int[100];
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

clang 3.0不再优化它,但后来的版本确实如此.

编辑2:

#include <new>  

int main()
{
    int* mem = new (std::nothrow) int[1000];

    if (mem != 0)
      return 1;

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

clang总是返回1.

c++ optimization gcc clang language-lawyer

66
推荐指数
4
解决办法
4867
查看次数

在C和C++中返回void类型

这编译没有任何警告.

这在C和C++中是合法的还是只在gcc和clang中工作?

如果它是合法的,那么在C99之后它是新东西吗?

void f(){

}

void f2(){
    return f();
}
Run Code Online (Sandbox Code Playgroud)

更新

正如"Rad Lexus"建议我试过这个:

$ gcc -Wall -Wpedantic -c x.c 
x.c: In function ‘f2’:
x.c:7:9: warning: ISO C forbids ‘return’ with expression, in function returning void [-Wpedantic]
  return f();
Run Code Online (Sandbox Code Playgroud)
$ clang -Wall -Wpedantic -c x.c 
x.c:7:2: warning: void function 'f2' should not return void expression [-Wpedantic]
        return f();
        ^      ~~~~~
1 warning generated.
Run Code Online (Sandbox Code Playgroud)
$ gcc -Wall -Wpedantic -c x.cc
(no errors)
Run Code Online (Sandbox Code Playgroud)
$ clang -Wall -Wpedantic -c x.cc
(no errors)
Run Code Online (Sandbox Code Playgroud)

更新 …

c c++ gcc clang language-lawyer

65
推荐指数
3
解决办法
9538
查看次数

在 C++ 中,用自身初始化全局变量是否具有未定义的行为?

int i = i;

int main() { 
 int a = a;
 return 0;
} 
Run Code Online (Sandbox Code Playgroud)

int a = a肯定有未定义的行为 (UB),关于它的更多细节在 读取未初始化的值总是未定义的行为吗?或者有例外吗?.

但是呢int i = i?在 C++ 中,我们可以为全局变量分配非常量值。i在遇到声明之前声明并零初始化(因为它具有文件范围)。在这种情况下,我们将0在定义的后面分配给它。可以说这没有 UB 吗?

c++ undefined-behavior language-lawyer

64
推荐指数
2
解决办法
4029
查看次数