C++ 11中变量的定义如下(§3/ 6):
甲变量是由比非静态数据成员或对象的其他的基准的声明引入.变量的名称表示引用或对象.
因此,非静态数据成员引用不是变量.为什么这种区分是必要的?这里的理由是什么?
在之前的回答中,我回答了以下警告是由于'\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文字,如果该值不可表示,则该程序是不正确的.但它没有提及普通文字.
发生什么了?这只是一个标准的混乱还是我错过了什么?
假设我们有一个简单的流:
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++程序员的一个常见错误是从文件中读取以下内容:
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.
那么解释有什么问题? …
根据另一个答案,如果引用它的表达式是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.我在这里很困惑.我想我错过了一些愚蠢的话.
以下代码摘自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>();
在创建具有自定义形状的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
我正在尝试用C++实验2D物理引擎.到目前为止,似乎最受欢迎的是Box2D.不幸的是,Box2D是一个严格的身体物理引擎,并不能真正帮助我想要尝试的东西.
我希望能够定义一个具有多个由弹簧连接的顶点的形状,这样当这个形状与刚性或其他非刚性形状碰撞时,它的形状将是灵活的.
现在我试图想办法在Box2D中只使用刚体来做这个,但似乎总有缺陷:
那么用C++做这种物理的最佳方法是什么?优选地,不必编写整个物理引擎.也许我只是错过了Box2D的一个功能.也许这不是正确的选择.那么什么是正确的选择?
要迭代输入流,我们通常会使用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是一个类型时,不合格的IDSbegin并且end在类的范围查找_RangeT仿佛由类成员访问查找(3.4.5),并且如果任一个(或两者)找到至少一个声明,开始-EXPR和端-expr分别是__range.begin()和__range.end();否则,开始-EXPR和最终EXPR是
begin(__range)和end(__range) …
示例代码取自: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++ ×9
c++11 ×5
iostream ×2
visual-c++ ×2
box2d ×1
const-method ×1
definition ×1
eof ×1
game-physics ×1
inputstream ×1
iterator ×1
literals ×1
memory-leaks ×1
objective-c ×1
overloading ×1
physics ×1
point ×1
sprite-kit ×1
standards ×1
string ×1
type-traits ×1
variables ×1