2

在写回复时,我写了一些代码来挑战我对 const 指针如何工作的假设。我曾假设 const 指针不能被 delete 函数删除,但正如您从下面的代码中看到的那样,情况并非如此:

#include <new>
#include <string.h>

class TestA
{
    private:
        char *Array;
    public:
        TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
        ~TestA(){if(Array != NULL){ delete [] Array;} }

        char * const GetArray(){ return Array; }
};

int main()
{
    TestA Temp;
    printf("%s\n",Temp.GetArray());
    Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
    Temp.GetArray()[1] = ' '; 
    printf("%s\n",Temp.GetArray());
    //Temp.GetArray() = NULL //This doesn't work

    delete [] Temp.GetArray(); //This works?! How do I prevent this?
}

我的问题是,我如何将用户访问权传递给指针(以便他们可以像使用 char 数组一样使用它),同时通过最好抛出某种投诉或异常来使删除函数无法删除它?

4

5 回答 5

6

如果您的用户正在使用delete[]他们没有从 获得的指针new[],请用线索棒击打他们的头部。

可以取消引用指针但不能将指针传递给删除的原因有很多:

  • 其他人会删除它。
  • 这不是块的开始。
  • 它来自malloc或其他一些非new分配器。
  • 它具有静态而不是动态的生命周期。
  • 如果有自动生命周期。

其中一些将在运行时出现异常。其他人将在以后的某个时间导致崩溃。根据标准,所有这些都是“未定义的行为”。

假设应该是指针不能用作 的参数delete,除非另有明确说明。

如果入门级程序员犯了这个错误,请教育他们。如果“经验丰富”的开发人员正在这样做,请因为他们在简历上撒谎而解雇他们。


如果您只是想让他们这样做时受到伤害,请分配一个比需要大的数组,并且return Array + 1;. 现在,如果他们尝试使用delete[].

实际用途是它(更多)可能使程序在虚假的删除调用中崩溃,而有问题的函数仍在调用堆栈上。原来的地方可能会继续运行一段时间,最后在无辜的代码中崩溃。所以这可以帮助你抓住愚蠢的用户。

于 2011-10-10T17:14:01.237 回答
5
delete [] Temp.GetArray(); //This works?! How do I prevent this?

只要它返回char*或其他一些指针类型,你就无法阻止它;delete语句中的表达式是否为 无关紧要const,因为以下所有内容在 C++ 中都是完全有效的:

char *pc = f(); 
delete [] pc;  //ok

const char *pc = g(); 
delete [] pc; //ok

char * const pc = h(); 
delete [] pc; //ok

const char * const pc = k(); 
delete [] pc; //ok

但是,如果你改变这个:

char *Array;

对此

std::vector<char> Array;

然后您可以通过将其返回为:

std::vector<char> & GetArray() { return Array; }

底线是 :

在 C++ 中,动态数组的默认选择应该是std::vector<T>除非您有非常充分理由使用它。

于 2011-10-10T16:54:57.460 回答
1

您的 const 没有任何效果,您正在返回一个 const 指针,而不是指向 const char 的指针,这正是您想要的。另请参阅 Nawaz 关于使用向量的建议。

于 2011-10-10T17:11:29.020 回答
1

您真正能做的最多就是返回一些不可接受的操作数delete。这可以是一个 RAII 对象(如 std::vector 或 std::array),也可以是一个引用(取决于您的情况,可能是合适的)。

[Un]幸运的是,C++ 让程序员可以做各种偷偷摸摸的事情。

于 2011-10-10T17:42:19.823 回答
0

你不能完全阻止愚蠢,但你可以通过使用访问机制而不是返回实际的数组指针来扼杀它。

char& operator[](size_t index) { return Array[index]; }

这并没有解决将其视为 char 数组的能力,但正如已经指出的那样,如果您显示该指针,(坏)程序员可以随意对其进行删除。

于 2011-10-10T19:29:34.067 回答