小编R S*_*ahu的帖子

cout << a ++ << a ;?的正确答案是什么?

最近在一次采访中有一个以下客观类型的问题.

int a = 0;
cout << a++ << a;
Run Code Online (Sandbox Code Playgroud)

回答:

一个.10
b.01
c.未定义的行为

我回答了选择b,即输出为"01".

但令我惊讶的是,一位采访者告诉我,正确的答案是选项c:undefined.

现在,我确实知道C++中序列点的概念.以下语句的行为未定义:

int i = 0;
i += i++ + i++;
Run Code Online (Sandbox Code Playgroud)

但根据我对该陈述的理解cout << a++ << a,ostream.operator<<()将被召唤两次,先是ostream.operator<<(a++)后来ostream.operator<<(a).

我还检查了VS2010编译器的结果,其输出也是'01'.

c++ c++-faq

98
推荐指数
3
解决办法
8281
查看次数

为什么对于非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
查看次数

无符号和有符号整数的比较运算

请参阅此代码段

int main()
{ 
 unsigned int a = 1000;
 int b = -1;
 if (a>b) printf("A is BIG! %d\n", a-b);
 else printf("a is SMALL! %d\n", a-b); 
 return 0;
}   
Run Code Online (Sandbox Code Playgroud)

这给出了输出:a是SMALL:1001

我不明白这里发生了什么.>运算符如何在这里工作?为什么"a"小于"b"?如果它确实更小,为什么我得到一个正数(1001)作为差异?

c unsigned signed gcc

40
推荐指数
2
解决办法
4万
查看次数

为什么operator << std :: ostream和char之间的函数是非成员函数?

当我运行以下程序时

#include <iostream>

int main()
{
   char c = 'a';
   std::cout << c << std::endl;
   std::cout.operator<<(c) << std::endl;

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

我得到了输出

a
97
Run Code Online (Sandbox Code Playgroud)

http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt进一步挖掘,我注意到std::ostream::operator<<()没有char作为参数类型的重载.函数调用std::cout.operator<<(a)被解析为std::ostream::operator<<(int),这解释了输出.

我假设和operator<<之间的函数在其他地方声明为:std::ostreamchar

std::ostream& operator<<(std::ostream& out, char c);
Run Code Online (Sandbox Code Playgroud)

否则,std::cout << a将解决std::ostream::operator<<(int).

我的问题是为什么声明/定义为非成员函数?是否存在阻止其成为会员功能的已知问题?

c++ ostream c++11

36
推荐指数
2
解决办法
957
查看次数

为什么使用std :: less作为比较std :: map和std :: set中的键的默认函子?

我想知道为什么std::mapstd::set使用std::less默认仿函数来比较键.为什么不使用类似于strcmp的仿函数?就像是:

  template <typename T> struct compare
  {
     // Return less than 0 if lhs < rhs
     // Return 0 if lhs == rhs
     // Return greater than 0 if lhs > rhs
     int operator()(T const& lhs, T const& rhs)
     {
        return (lhs-rhs);
     }
  }
Run Code Online (Sandbox Code Playgroud)

说一个map有两个对象,用键key1key2.现在我们要插入另一个带键的对象key3.

使用时std::less,该insert功能需要先std::less::operator()key1和调用key3.假设std::less::operator()(key1, key3)返回false.它必须std::less::operator()再次通过键切换std::less::operator()(key3, key1),以决定是否key1等于 …

c++ stdmap stdset

35
推荐指数
2
解决办法
2140
查看次数

是否存在对类型名有效但对基本类型无效的语言结构?

我注意到伪析构函数调用在使用类型名称时有效,但在使用基本类型时则无效.

typedef int BType;
int b;
b.~BType();   // Legal
b.~int();     // Not legal
Run Code Online (Sandbox Code Playgroud)

可以在对另一个SO帖子的答案中找到对上述的解释.

类型名称的定义,来自C++ 11标准:

7.1.6.2简单类型说明符,p1

type-name:  
   class-name   
   enum-name  
   typedef-name  
   simple-template-id

当类型说明符是类型名称时是否有任何其他语言结构,但是当它是基本类型时无效,即使type-name表示基本类型,如上所示?

c++

28
推荐指数
1
解决办法
495
查看次数

为什么指向int的指针转换为void*但指向函数的指针转换为bool?

C++草案标准(N3337)有关于指针转换的以下内容:

4.10指针转换

2类型的右值"指针CV T ",其中T是对象类型,可被转化为式的一个右值"指针CV void ".一个"指针转换的结果CV T "发送给"指针CV void "指向类型对象T所在的存储位置的起始位置,就好像该对象是类型最派生的对象(1.8)T(即不是基类子对象).

4.12布尔转换

1算术,枚举,指针或指向成员类型的指针的右值可以转换为类型的右值bool.零值,空指针值或空成员指针值转换为false; 任何其他值都转换为true

基于以上所述,将函数指针或指针转换int为a void*也是完全可以的bool.

但是,考虑到两者的选择,指针应该转换为哪一个?

然后,为什么指向函数的指针转换为a bool和指向int转换为void*?的指针?

程序:

#include <iostream>
using namespace std;

void foo(const void* ptr)
{
   std::cout << "In foo(void*)" << std::endl;
}

void foo(bool b)
{
   std::cout << "In foo(bool)" << std::endl;
}

void bar()
{
}

int main()
{
   int i …
Run Code Online (Sandbox Code Playgroud)

c++ pointers c++11

24
推荐指数
1
解决办法
1806
查看次数

在NULL指针上调用delete - C++ 03 vs C++ 11

在C++ 03标准中,我看到:

5.3.5删除

2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在任一替代方案中,如果操作数的值delete是空指针,则操作无效.在第一个备选(删除对象)中,操作数的值delete应该是指向非数组对象的指针或指向表示此类对象的基类的子对象(1.8)的指针(第10节).如果不是,则行为未定义.在第二种方法(删除数组)中,操作数的delete值必须是由前一个数组new-expression产生的指针值.72)如果不是,则行为是未定义的.

在C++ 11 Draft Standard(N3337)中,我看到:

5.3.5删除

2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在第一个替代(删除对象)中,操作数的值delete可以是空指针值,指向由前一个新表达式创建的非数组对象的指针,或指向表示基础的子对象(1.8)的指针这类对象的类别(第10条).如果不是,则行为未定义.在第二个备选(删除数组)中,delete的操作数的值可以是空指针值或由先前数组new-expression产生的指针值.如果不是,则行为未定义.

我已经强调了两个标准中规范之间的差异.我觉得奇怪的是,2003标准更加强调必须如何处理NULL指针,而2011标准没有说明实现必须做什么.

  1. C++ 11标准的措辞是否在草案标准和实际标准之间发生了变化?如果是这样,怎么样?

  2. 如果标准草案的措辞在实际标准中保持不变,那么在2003年和2011年之间将强有力的陈述改为几乎没有任何理由的理由是什么?

c++ language-lawyer delete-operator c++11 c++03

21
推荐指数
2
解决办法
3477
查看次数

为什么我能够为匿名函数指针变量分配函数引用?

以下代码编译得很好,我不知道为什么.有人可以向我解释为什么这是合法的吗?

我正在使用g ++(Debian 6.1.1-10)6.1.1 20160724进行编译.

#include <iostream>

int sum(int x, int y) { return x + y; }

int main(int argc, char *argv[])
{
    using std::cout;

    int (*) (int, int) = &sum;
    cout << "what" << '\n';
}
Run Code Online (Sandbox Code Playgroud)

附录

以下程序使用g ++版本5.4.0进行编译,但无法在gcc中编译.

int main()
{
    int (*) = 20;
}
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer

20
推荐指数
1
解决办法
271
查看次数

为什么以及何时使用__noop?

我正在阅读__noop和MSDN示例

#if DEBUG
   #define PRINT   printf_s
#else
   #define PRINT   __noop
#endif

int main() {
   PRINT("\nhello\n");
}
Run Code Online (Sandbox Code Playgroud)

我没有看到只有空宏的好处:

#define PRINT
Run Code Online (Sandbox Code Playgroud)

生成的代码是相同的.什么是使用__noop它的有效例子实际上使它有用?

c++ intrinsics visual-c++

19
推荐指数
2
解决办法
3141
查看次数