有没有什么好的理由(除了"宏是邪恶的",也许)不使用以下宏?
#define DELETE( ptr ) \
if (ptr != NULL) \
{ \
delete ptr; \
ptr = NULL; \
}
#define DELETE_TABLE( ptr ) \
if (ptr != NULL) \
{ \
delete[] ptr; \
ptr = NULL; \
}
Run Code Online (Sandbox Code Playgroud) 可能重复:
为什么你想要在堆而不是堆栈上分配内存?
Test2 *t2 = new Test2();
t2->test();
Test2 t3;
t3.test();
Run Code Online (Sandbox Code Playgroud)
为什么我要创建Test2类型的指针对象?为什么不做Test2的非指针版本?我为什么要做指针对象?
在这里找到答案:
根据C++标准(3.7.3.2/4)使用(不仅是解除引用,还有复制,转换,其他任何),无效指针是未定义的行为(如果有疑问也会看到这个问题).现在,遍历STL容器的典型代码如下所示:
std::vector<int> toTraverse;
//populate the vector
for( std::vector<int>::iterator it = toTraverse.begin(); it != toTraverse.end(); ++it ) {
//process( *it );
}
Run Code Online (Sandbox Code Playgroud)
std::vector::end()是超出容器最后一个元素的假设元素的迭代器.那里没有元素,因此使用指针通过迭代器是未定义的行为.
那么!= end()工作怎么样呢?我的意思是为了进行比较,需要构造迭代器包装无效地址,然后必须在比较中使用该无效地址,这也是未定义的行为.这样的比较合法吗?为什么?
在另一个问题的热门评论主题之后,我开始讨论C99标准中有关C数组的内容和内容.
基本上,当我定义一个2D数组时int a[5][5],标准C99是否保证它将是一个连续的整数块,我可以将它投射到(int *)a并确保我将拥有一个25个整数的有效一维数组.
正如我理解标准的那样,上面的属性隐含在sizeof定义和指针算术中,但其他人似乎不同意并且说铸造到(int*)上面的结构给出了一个未定义的行为(即使他们同意所有现有的实现实际分配连续的价值观).
更具体地说,如果我们认为一种实现可以检测数组检查所有维度的数组边界并在访问1D数组时返回某种错误,或者不能正确访问第1行以上的元素.这样的实施可以是标准的编制吗?在这种情况下,C99标准的哪些部分是相关的.
在阅读这个问题的答案时,我注意到答案(例如这个)意味着operator delete即使在delete空指针上执行语句时也可以调用它.
所以我写了一个小片段:
class Test {
public:
void* operator new( size_t ) { /*doesn't matter*/ return 0; }
void operator delete( void* ptr ) {
ptr; //to suppress warning and have a line to put breakpoint on
}
};
int main()
{
Test* ptr = 0;
delete ptr;
}
Run Code Online (Sandbox Code Playgroud)
并且 - 令我惊讶的是 - Test::operator delete()通过ptr持有空指针来调用.
据我所知,它operator new分配内存operator delete并将内存返回给分配器.如果我delete在空指针上调用语句,则意味着指针后面没有对象,并且没有内存返回到分配器.
delete语句包括调用析构函数.当我传递一个空指针时,肯定不会调用析构函数--C++会处理这个问题.那么为什么operator delete在这种情况下被调用?
我有一个返回地址的函数如下
struct node *create_node(int data)
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data=data;
temp->next=NULL;
printf("create node temp->data=%d\n",temp->data);
return temp;
}
Run Code Online (Sandbox Code Playgroud)
struct node是哪里的
struct node {
int data;
struct node *next;
};
Run Code Online (Sandbox Code Playgroud)
如何在printf("")中查看存储在temp中的地址?
更新
如果我检查gdb中的地址,地址将以十六进制数格式显示,即0x602010,其中相同的地址printf("%p",temp)输入不同的数字,这与我在gdb打印命令中看到的不同.
我有一个程序可以接受命令行参数,我想从一个函数访问用户输入的参数.如何传递的*argv[],从int main( int argc, char *argv[])那个函数?我对指针的概念不熟悉,*argv[]看起来有点过于复杂,我无法自己解决这个问题.
我的想法是main通过将我想要对参数执行的所有工作移动到库文件来尽可能保持干净.当我设法把它们拿到外面时,我已经知道我要对这些论点做些什么main.我只是不知道如何让他们到那里.
我正在使用GCC.提前致谢.
以下函数的最通用语法是什么:
template<IteratorType> void myFunction(const IteratorType& myIterator)
{
_ptr = &myIterator[0];
}
Run Code Online (Sandbox Code Playgroud)
它需要一个迭代器myIterator(它可以是一个原始指针),目标是将指向的对象的地址分配myIterator给一个原始指针_ptr.目前我使用&myIterator[0]但我意识到只有随机访问迭代器才有operator [].
那么有一种语法适用于所有类型的标准迭代器和指针吗?
这是我的一本书中的一个问题(没有附上答案),我已经考虑了几天了.答案很简单,C++代码最终会崩溃,因为它在每次迭代后都会创建一个垃圾内存单元?
考虑以下Java和C++代码片段,这是基于GUI的应用程序的两个版本的一部分,它收集用户首选项并使用它们来组装命令及其参数.方法/函数getUserCommandSpecification()返回表示命令代码及其参数的字符串.返回的字符串用于构建所需的命令,然后执行该命令.
假设如下:
(i)在Command对象的while循环中创建(在Java情况下由cmd引用或在C++情况下由cmd指向),不再引用或使用对生成的对象的引用/指针cmd.
(ii)应用程序还定义了一个类Command及其方法/函数execute().
一个.下面详述的两个代码版本中的哪一个最终会崩溃.
湾 解释为什么程序版本崩溃而另一个版本没有崩溃.
Java代码
...
while (true) {
String commandSpecification = getUserCommandSpecification();
Command cmd = new Command(commandSpecification);
cmd.execute();
}
...
Run Code Online (Sandbox Code Playgroud)
C++代码
...
while (true) {
string commandSpecification = getUserCommandSpecification();
Command* cmd = new Command(commandSpecification);
cmd -> execute();
}
...
Run Code Online (Sandbox Code Playgroud) 我读到你不能在指针上做bitmasks,为什么你不能对指针进行按位操作?
有没有办法达到同样的效果?
这同样适用于C++吗?