Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 停止运算符delete上的隐式强制转换_C++_Memory Management_Implicit Conversion - Fatal编程技术网

C++ 停止运算符delete上的隐式强制转换

C++ 停止运算符delete上的隐式强制转换,c++,memory-management,implicit-conversion,C++,Memory Management,Implicit Conversion,My String类提供了一个运算符char*重载,允许您将字符串传递给C函数 不幸的是,我的一位同事无意中发现了一个bug 他实际上拥有以下代码 StringT str; // Some code. delete str; 是否有任何方法可以防止delete将string对象强制转换为char*以防止将来出现类似这样的错误std::string通过不提供char操作符重载来解决这个问题,但理想情况下,我希望保持重载,但阻止删除工作 是否存在阻止delete将字符串对象强制转换为char* 是

My String类提供了一个运算符char*重载,允许您将字符串传递给C函数

不幸的是,我的一位同事无意中发现了一个bug

他实际上拥有以下代码

StringT str;
// Some code.
delete str;
是否有任何方法可以防止delete将string对象强制转换为char*以防止将来出现类似这样的错误
std::string
通过不提供char操作符重载来解决这个问题,但理想情况下,我希望保持重载,但阻止删除工作

是否存在阻止delete将字符串对象强制转换为char*

是的:避开隐式铸造操作符。这已经被宣扬了至少十年了。相信它,你就会过上更幸福的生活

是否存在阻止delete将字符串对象强制转换为char*


是的:避开隐式铸造操作符。这已经被宣扬了至少十年了。相信它,你就会过上更幸福的生活

信不信由你,std::string不提供隐式转换是有原因的,创建c_str()函数不仅仅是为了激怒你。提供隐式转换,你将面临一个模棱两可和痛苦的世界。

信不信由你,std::string不提供隐式转换是有原因的,创建c_str()函数不仅仅是为了激怒你。提供隐式转换,你将自己置身于一个模棱两可和痛苦的世界。

有争议的意见时间:如果有人编写的代码受到这种“错误”的困扰,他们应该被咬一口

套用你的问题:

我怎样才能防止人们用我的枪射中自己的脚

你不能。我不同意你的意见,说你的超负荷是可以的。如果这会导致某人的代码出现问题,那是因为某人不知道C++,不应该对它进行编码。 你要担心的问题比那些对语言理解不够透彻,不知道如何
删除
非指针的东西的人是否会滥用你的类更大


我对C++比较陌生,没有见过一些灰蒙蒙的老兵的恐怖。一个特别糟糕的模棱两可的例子可能会让我相信我的邪恶方式。然而,事实并非如此。

有争议的意见时间:如果有人编写的代码受到这种“错误”的困扰,他们应该被咬一口

套用你的问题:

我怎样才能防止人们用我的枪射中自己的脚

你不能。我不同意你的意见,说你的超负荷是可以的。如果这会导致某人的代码出现问题,那是因为某人不知道C++,不应该对它进行编码。 你要担心的问题比那些对语言理解不够透彻,不知道如何
删除
非指针的东西的人是否会滥用你的类更大


我对C++比较陌生,没有见过一些灰蒙蒙的老兵的恐怖。一个特别糟糕的模棱两可的例子可能会让我相信我的邪恶方式。然而,事实并非如此。

是的。通过声明(但不定义!)
运算符char const volatile*
提供两个隐式强制转换。当您将
StringT
传递给C字符串函数时,重载解析仍将选择原始
运算符char const*
(精确匹配)。但
删除str现在变得模棱两可


声明可以是私有的,因此如果以某种方式选择它,则将是编译时错误。预期的模糊性发生在重载解析之前-专用的
仅用于捕捉极少数情况,其中会以某种方式选择
volatile
重载。

是。通过声明(但不定义!)
运算符char const volatile*
提供两个隐式强制转换。当您将
StringT
传递给C字符串函数时,重载解析仍将选择原始
运算符char const*
(精确匹配)。但
删除str现在变得模棱两可

struct Dummy {};
class StringT {
public:
    // ........
    operator char*() { /*...*/ }
    operator const char*() const { /*...*/ }

    operator const Dummy* () const { return 0; }
    operator Dummy* () { return 0; }
};

/// ...
void g(const char * ) { /*...*/ }

int main() {

    StringT str;
    g(str); // OK
    delete str; //error C2440: 'delete' : cannot convert from 'StringT' to 'void *'
    return 0;
}

声明可以是私有的,因此如果以某种方式选择它,则将是编译时错误。预期的模糊性发生在重载解析之前。
private
仅用于捕捉极少数情况,其中会以某种方式选择
volatile
重载。

是的-不要
删除非指针的内容。你为什么关心阻止人们做本来不该做的事情?不仅如此,而且不要删除那些不是指向
新对象的
对象。@sbi-这是一个参数。简单地否认这一点并不能减少争论。我理解为什么
删除str在这里起作用,但OP会问“我如何防止人们变得愚蠢?”答案是“你不能”。你可以给人们一个关于他们能做什么和不能做什么的非常狭隘的定义,或者你可以给人们足够的绳子来吊死自己,看看他们是否能设法用它搭建一座绳桥。使用C++已经说过“我可以做我自己的内存管理!”所以我不认为有必要对绳子这么严格。我看它的时候,编译时间类型的唯一目的是阻止人们做这种愚蠢的事情。在这种情况下,对象
str
不支持删除操作,但表达式
delete str
会编译。这显然是类型
StringT
中的一个缺陷,剩下的问题是这是否是方便的字符*转换的可接受成本。这与类型正确但值错误的愚蠢行为完全不同,例如删除不是来自

struct Dummy {};
class StringT {
public:
    // ........
    operator char*() { /*...*/ }
    operator const char*() const { /*...*/ }

    operator const Dummy* () const { return 0; }
    operator Dummy* () { return 0; }
};

/// ...
void g(const char * ) { /*...*/ }

int main() {

    StringT str;
    g(str); // OK
    delete str; //error C2440: 'delete' : cannot convert from 'StringT' to 'void *'
    return 0;
}