我正在阅读我的C++讲师的一些讲义,他写了以下内容:
- 使用缩进//确定
- 永远不要依赖运算符优先级 - 始终使用括号//确定
- 总是使用{}块 - 即使是单行// 不行,为什么???
- 比较左侧的Const对象// OK
- 对于> = 0 //好玩法的变量使用无符号
- 删除后将指针设置为NULL - 双删除保护//不错
第三种技术对我来说并不清楚:通过在一条线中放置一条线可以获得{ ... }什么?
例如,拿这个奇怪的代码:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
{
if (i % 2 == 0)
{
j++;
}
}
Run Code Online (Sandbox Code Playgroud)
并替换为:
int j = 0;
for (int i = 0 ; i < 100 ; ++i)
if (i % 2 == 0)
j++;
Run Code Online (Sandbox Code Playgroud)
使用第一个版本有什么好处?
我总是想知道为什么在删除后将指针自动设置为NULL 不是标准的一部分.如果这一点得到解决,那么由于指针无效而导致的许多崩溃都不会发生.但是,我已经说过,我可以想到为什么标准会限制这个:
性能:
额外的指令可能会降低
delete性能.可能是因为
const指针.然后标准可能已经为这个特殊情况做了一些事情我想.
有没有人知道不允许这个的确切原因?
在C(或C++)中,指针是特殊的,如果它们的值为零:我建议在释放内存后将指针设置为零,因为这意味着再次释放指针并不危险; 当我调用malloc时,如果它无法获取内存,则返回一个值为零的指针; 我一直用if (p != 0)它来确保传递的指针是有效的,等等.
但是,由于内存寻址从0开始,因此有效地址不是0吗?如果是这样的话,0如何用于处理空指针?为什么不是负数而是null?
编辑:
一堆好的答案.我将总结在所表达的答案中所说的内容,因为我自己的思想解释了它,并希望如果我误解,社区将纠正我.
就像编程中的其他一切一样,它是一种抽象.只是一个常量,与地址0并不真正相关.C++ 0x通过添加关键字来强调这一点nullptr.
它甚至不是地址抽象,它是C标准指定的常量,只要它确保它永远不等于"真实"地址,编译器就可以将它转换为其他数字,如果0不是,则等于其他空指针用于平台的最佳价值.
如果它不是抽象,早期就是这种情况,系统使用地址0,程序员不受限制.
我承认,我的负面数字建议是一个狂热的头脑风暴.对地址使用有符号整数有点浪费,如果它意味着除了空指针(-1或其他)之外,值空间在产生有效地址的正整数和刚刚浪费的负数之间均匀分配.
如果任何数字总是可以由数据类型表示,那么它就是0.(也可能是1.我想的是一位整数,如果是无符号则为0或1,或者只有符号的有符号位,或两位整数,将是[-2,1].但是你可以只得0为空,1是内存中唯一可访问的字节.)
还有一些东西在我的脑海里没有得到解决.Stack Overflow问题指向特定固定地址的指针告诉我,即使0表示空指针是抽象,其他指针值也不一定.这导致我发布另一个Stack Overflow问题,我是否可以访问地址零?.
似乎有两个论点为什么人们应该NULL在释放它们之后设置指针.
简短:free()不小心召唤第二次,当它被设置为时,不会崩溃NULL.
几乎总是这掩盖了一个逻辑错误,因为没有理由free()第二次调用.让应用程序崩溃并能够修复它会更安全.
它不能保证崩溃,因为有时在同一地址分配新内存.
当有两个指向同一地址的指针时,主要发生双重自由.
逻辑错误也可能导致数据损坏.
短:malloc()除非释放指针设置为,否则访问释放的指针可能会导致数据损坏,如果在同一位置分配内存NULL
NULL如果偏移足够大(someStruct->lastMember,theArray[someBigNumber]),则无法保证在访问指针时程序崩溃.而不是崩溃将导致数据损坏.
将指针设置为NULL无法解决具有相同指针值的不同指针的问题.
随意扩展这个问题.
我写了一个简单的,工作的俄罗斯方块游戏,每个块作为类单块的一个实例.
class SingleBlock
{
public:
SingleBlock(int, int);
~SingleBlock();
int x;
int y;
SingleBlock *next;
};
class MultiBlock
{
public:
MultiBlock(int, int);
SingleBlock *c, *d, *e, *f;
};
SingleBlock::SingleBlock(int a, int b)
{
x = a;
y = b;
}
SingleBlock::~SingleBlock()
{
x = 222;
}
MultiBlock::MultiBlock(int a, int b)
{
c = new SingleBlock (a,b);
d = c->next = new SingleBlock (a+10,b);
e = d->next = new SingleBlock (a+20,b);
f = e->next = new SingleBlock (a+30,b);
}
Run Code Online (Sandbox Code Playgroud)
我有一个扫描完整行的函数,并运行删除相关的块的链接列表并重新分配 - >下一个指针. …
我用这段代码在C++中试验析构函数:
#include <iostream>
struct temp
{
~temp() { std::cout << "Hello!" << std::endl; }
};
int main()
{
temp t;
t.~temp();
}
Run Code Online (Sandbox Code Playgroud)
我看到"你好!" 正在打印两次.不应该调用析构函数释放对象,并且当它超出范围时不应该再次调用析构函数吗?或者还有其他一些概念吗?
(我不打算在实践中这样做.我只是想了解这里发生了什么.)
搜索SO上的内容,我偶然发现了这个问题,其中一条评论得到了最多投票的回答(对最多投票答案的第五条评论)表明这delete p; p = NULL;是一个反模式.我必须承认,我碰巧经常使用它,有时候大部分时间都用它来检查if (NULL != p).Man自己似乎在暗示它(请参阅destroy()函数示例),所以我真的很困惑为什么它可能是一个可怕的事情被认为是反模式.我使用它的原因如下:
请注意,我不是在"this"指针的上下文中提出这个问题,让我们假设我们不是生活在一个完美的C++世界中,并且遗留代码确实存在并且必须进行维护,所以请不要建议任何一种智能指针:).
(*)据我所知,标准允许实现修改运算delete符的操作数,但是大多数实现都不这样做.
int* ptr = new int(0);
delete ptr; //delete is allowed to modify ptr, for example set it to 0
std::cout << ptr; // UB?
Run Code Online (Sandbox Code Playgroud)
承认(*),是否以ptr(以打印的形式)明确定义的读数?
如果delete修改ptr,是否允许设置陷阱值,这将使读取ptrUB?
我无法理解这段代码的结尾(array = 0;):
#include <iostream>
int main()
{
std::cout << "Enter a positive integer: ";
int length;
std::cin >> length;
int *array = new int[length];
std::cout << "I just allocated an array of integers of length " << length << '\n';
array[0] = 5; // set element 0 to value 5
delete[] array; // use array delete to deallocate array
array = 0; // use nullptr instead of 0 in C++11
return 0;
}
Run Code Online (Sandbox Code Playgroud)
最后,删除动态分配的数组(返回到OS),然后分配值0.
为什么这样做?数组返回操作系统后,无需为其赋值0,对吗?
代码来自:http …
我正在查看我在网上找到的以下链接列表代码:
void DeleteAfter(Node **head){
if(*head==NULL){
return;
}else{
Node *temp = NULL;
temp = (*head)->next;
(*head)->next = (*head)->next->next;
delete temp;
temp=NULL;
}
}
Run Code Online (Sandbox Code Playgroud)
我不熟悉C++,所以这可能是一个糟糕的问题,但为什么temp被删除后被设置为NULL?这是必要的一步吗?
c++ ×9
pointers ×4
c ×3
arrays ×1
c++-faq ×1
coding-style ×1
curly-braces ×1
destructor ×1
free ×1
memory ×1