小编Jos*_*eld的帖子

为什么非静态数据成员引用不是变量?

C++ 11中变量的定义如下(§3/ 6):

变量是由比非静态数据成员或对象的其他的基准的声明引入.变量的名称表示引用或对象.

因此,非静态数据成员引用不是变量.为什么这种区分是必要的?这里的理由是什么?

c++ variables standards definition c++11

10
推荐指数
1
解决办法
876
查看次数

'\ u0B95'是多字符文字吗?

之前的回答中,我回答了以下警告是由于'\u0B95'需要三个字节的事实引起的,因此是一个多字符文字:

warning: multi-character character constant [-Wmultichar]
Run Code Online (Sandbox Code Playgroud)

但实际上,我不认为我是对的,我不认为gcc也是.标准规定:

包含多个c-char的普通字符文字是多字符文字.

c-char的一个生产规则是通用字符名称(即\uXXXX\UXXXXXXXX).由于\u0B95是单个c-char,因此这不是多字符文字.但现在它变得凌乱.该标准还说:

包含单个c-char的普通字符文字具有类型char,其值等于执行字符集中c-char的编码的数值.

所以我的文字具有char执行字符集中字符的类型和值(如果该集合中不存在,则为实现定义的值).char只被定义为足够大以存储基本字符集的任何成员(实际上不是由标准定义的,但我认为它意味着基本的执行字符集):

声明为字符(char)的对象应足够大,以存储实现的基本字符集的任何成员.

因此,由于执行字符集是a char可以容纳的所有值的超集,因此我的角色可能不适合char.

那么什么样的价值确实char有吗?这似乎没有在任何地方定义.该标准确实说,对于char16_t文字,如果该值不可表示,则该程序是不正确的.但它没有提及普通文字.

发生什么了?这只是一个标准的混乱还是我错过了什么?

c++ literals character-encoding c++11

10
推荐指数
1
解决办法
483
查看次数

为什么从流中提取字符串会设置eof位?

假设我们有一个简单的流:

hello
Run Code Online (Sandbox Code Playgroud)

请注意,\n文本文件中通常没有额外的内容.现在,以下简单代码显示eof在提取单个数据后在流上设置该位std::string.

int main(int argc, const char* argv[])
{
  std::stringstream ss("hello");
  std::string result;
  ss >> result;
  std::cout << ss.eof() << std::endl; // Outputs 1
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,我不明白为什么会根据标准发生这种情况(我正在阅读C++ 11 - ISO/IEC 14882:2011(E)).operator>>(basic_stream<...>&, basic_string<...>&)被定义为表现得像格式化的输入函数.这意味着它构造了一个sentry对象,它继续吃掉空白字符.在这个例子中,没有,所以sentry构造完成没有问题.转换为a时bool,sentry对象给出true,因此提取器继续继续实际提取字符串.

然后将提取定义为:

提取并附加字符,直到出现以下任何一种情况:

  • n 字符存储;
  • 文件结束发生在输入序列上;
  • isspace(c,is.getloc())对于下一个可用的输入字符c,则为true .

在提取最后一个字符(如果有)之后,调用is.width(0)并销毁sentry对象k.如果函数没有提取任何字符,则会调用is.setstate(ios::failbit),这可能会抛出ios_base::failure(27.5.5.4).

这里没有任何东西实际上导致该eof位被设置.是的,如果提取到达文件结尾,则提取停止,但它不会设置该位.事实上,eof只有当我们做另一个时才应该设置该位ss >> result;,因为当sentry …

c++ string iostream language-lawyer

10
推荐指数
1
解决办法
1122
查看次数

不使用EOF位作为流提取条件的真正原因是什么?

灵感来自我之前的问题

新C++程序员的一个常见错误是从文件中读取以下内容:

std::ifstream file("foo.txt");
std::string line;
while (!file.eof()) {
  file >> line;
  // Do something with line
}
Run Code Online (Sandbox Code Playgroud)

他们经常会报告文件的最后一行被读取两次.这个问题的常见解释(我之前给出的一个)类似于:

如果您尝试提取文件结尾,则提取将仅在流上设置EOF位,而不是如果您的提取仅在文件结尾处停止.file.eof()只会告诉你上一次读取是否到达文件结尾,而不是下一次读取.在提取最后一行之后,EOF位仍未设置,并且再次发生迭代.但是,在最后一次迭代中,提取失败并且line仍然具有与之前相同的内容,即最后一行是重复的.

但是,这个解释的第一句是错误的,因此对代码所做的解释也是错误的.

格式化输入函数的定义(即operator>>(std::string&))将提取定义为使用rdbuf()->sbumpc()rdbuf()->sgetc()获取输入字符.它声明如果这些函数中的任何一个返回traits::eof(),则设置EOF位:

如果rdbuf()->sbumpc()rdbuf()->sgetc()返回traits::eof(),那么输入函数,除非另有明确说明,否则完成其操作,并且在返回之前setstate(eofbit)可以抛出ios_base::failure(27.5.5.4).

我们可以通过使用std::stringstream而不是文件的简单示例来看到这一点(它们都是输入流,并且在提取时表现相同):

int main(int argc, const char* argv[])
{
  std::stringstream ss("hello");
  std::string result;
  ss >> result;
  std::cout << ss.eof() << std::endl; // Outputs 1
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

很明显,这里的单次提取获得hello从字符串设置EOF位为1.

那么解释有什么问题? …

c++ iostream eof language-lawyer

10
推荐指数
1
解决办法
5725
查看次数

使用右值引用延长临时的生命周期

根据另一个答案,如果引用它的表达式是xvalue表达式,则右值引用不会延长临时值的生命周期.因为std::move返回一个右值引用,所以调用它的表达式是一个xvalue,所以下面的结果是一个悬空引用:

int main()
{
  std::string&& danger = std::move(get_string());  // dangling reference !
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

没关系.在std::move没有意义在这里; 它已经是一个左值.

但是这里我正在画一个空白.将xvalue表达式作为参数传递,完全标准使用std::move和rvalue引用有何不同?

void foo(const std::string& val);
// More efficient foo for temporaries:
void foo(std::string&& val);

int main()
{
  std::string s;
  foo(std::move(s)); // Give up s for efficiency
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

rvalue引用参数是否有一个特殊规则,它将延长临时的生命周期,无论它是prvalue还是xvalue?或者std::move调用表达式只是一个xvalue,因为我们传递了一个已经是rvalue的东西?我不这么认为,因为它总是返回一个右值引用,这是一个xvalue.我在这里很困惑.我想我错过了一些愚蠢的话.

c++ rvalue-reference move-semantics c++11

9
推荐指数
2
解决办法
2052
查看次数

const临时从模板类型和为什么使用std :: add_const?

以下代码摘自cppreference.com.

#include <iostream>
#include <type_traits>

struct foo
{
    void m() { std::cout << "Non-cv\n"; }
    void m() const { std::cout << "Const\n"; }
};

template <class T>
void call_m()
{
    T().m();
}

int main()
{
    call_m<foo>();
    call_m<std::add_const<foo>::type>();
}
Run Code Online (Sandbox Code Playgroud)

但是,使用VC++ 2012年11月的CTP编译时,输出为

非CV

非CV

而不是预期的:

非CV

常量

此外,以下两个陈述之间的区别是什么:

call_m<const foo>();

call_m<std::add_const<foo>::type>();

c++ overloading type-traits visual-c++ c++11

9
推荐指数
1
解决办法
472
查看次数

SKPhysicsBody bodyWithPolygonFromPath内存泄漏

在创建具有自定义形状的Sprite Kit物理主体时,我有一个奇怪的内存泄漏.这就是我的实现的样子:

CGFloat offsetX = self.frame.size.width * self.anchorPoint.x;
CGFloat offsetY = self.frame.size.height * self.anchorPoint.y;

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, 4 - offsetX, 3 - offsetY);
CGPathAddLineToPoint(path, NULL, 66 - offsetX, 3 - offsetY);
CGPathAddLineToPoint(path, NULL, 35 - offsetX, 57 - offsetY);
CGPathCloseSubpath(path);

self.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path];

CGPathRelease(path);
Run Code Online (Sandbox Code Playgroud)

内部SKSpriteNode方法一切都在进行中.在创建这样的实体后,Instruments会告诉我几个内存泄漏:

Leaked object: 
  Malloc 32 Bytes
Size:
  32 Bytes
Responsible Library: 
  PhysicsKit
Responsible Frame:
  std::__1::__split_buffer<PKPoint, std::__1::allocator<PKPoint>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<PKPoint>&)
Run Code Online (Sandbox Code Playgroud)

CGPathRelease(path);条线是必要的 - 没有它我会得到更多的内存泄漏,CGPath这是可以理解的.当我使用此实现时(用于测试目的):

CGFloat radius = …
Run Code Online (Sandbox Code Playgroud)

memory-leaks objective-c game-physics sprite-kit skphysicsbody

9
推荐指数
1
解决办法
2667
查看次数

C++中的非刚体2D物理引擎

我正在尝试用C++实验2D物理引擎.到目前为止,似乎最受欢迎的是Box2D.不幸的是,Box2D是一个严格的身体物理引擎,并不能真正帮助我想要尝试的东西.

我希望能够定义一个具有多个由弹簧连接的顶点的形状,这样当这个形状与刚性或其他非刚性形状碰撞时,它的形状将是灵活的.

现在我试图想办法在Box2D中只使用刚体来做这个,但似乎总有缺陷:

  1. 使用矩形或线段作为柔性形状的外边缘.这些会与其他形状碰撞.不幸的是,它们没有弹性,所以不会看到预期的效果.
  2. 形状的每个顶点可以是具有其自己的小圆形形状的主体.然后可以通过弹簧将这些主体连接在一起.这在形状变形方面效果很好,但想象一下,如果形状落在刚性钉上并且尖钉刚好在顶点之间穿过.然后形状会卡在钉子上.

那么用C++做这种物理的最佳方法是什么?优选地,不必编写整个物理引擎.也许我只是错过了Box2D的一个功能.也许这不是正确的选择.那么什么是正确的选择?

c++ physics point box2d

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

输入流上基于范围的循环

要迭代输入流,我们通常会使用std::istream_iterator如下:

typedef std::istream_iterator<std::string> input_iterator;

std::ifstream file("myfile");
for (input_iterator i(file); i != input_iterator(); i++) {
  // Here, *i denotes each element extracted from the file
}
Run Code Online (Sandbox Code Playgroud)

如果我们可以使用基于范围的for语句来迭代输入流,那就太好了.但是,对于类的对象,范围为基础的for需要的对象具有begin()end()成员函数(§6.5.4,粗体强调):

  • 如果_RangeT是一个数组类型,开始-EXPR最终EXPR__range__range + __bound分别,其中__bound在阵列的约束.如果_RangeT是未知大小的数组或不完整类型的数组,则该程序格式不正确;

  • 如果_RangeT是一个类型时,不合格的IDS begin并且end在类的范围查找_RangeT仿佛由类成员访问查找(3.4.5),并且如果任一个(或两者)找到至少一个声明,开始-EXPR端-expr分别是__range.begin()__range.end();

  • 否则,开始-EXPR最终EXPRbegin(__range)end(__range) …

c++ iterator inputstream c++11

8
推荐指数
2
解决办法
2898
查看次数

为什么const临时选择在const const上调用非const成员函数?

示例代码取自:http://en.cppreference.com/w/cpp/types/add_cv (我修改了一下.)

struct foo
{
    void m() { std::cout << "Non-cv\n"; }
    void m() const { std::cout << "Const\n"; }
};

template<class T>
void call_m()
{
  T().m();
}

int main()
{
    call_m<foo>();
    call_m<const foo>(); //here
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Non-cv
Non-cv
Run Code Online (Sandbox Code Playgroud)

在第二次调用中,T是const限定的,所以T()应该调用const版本,对吧?还是有一些我错过的特殊规则?

c++ visual-c++ const-method visual-studio-2012

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