【问题标题】:Why can I convert 0 to an std::shared_ptr<T> but not 1?为什么我可以将 0 转换为 std::shared_ptr<T> 而不是 1?
【发布时间】:2019-01-25 12:12:52
【问题描述】:
#include <memory>

void f1(std::shared_ptr<bool> ptr) {}

int main() {
    f1(0); // OK
    f1(1); // compilation error: could not convert ‘1’ from ‘int’ to ‘std::shared_ptr<bool>’
}

都是int,为什么01可以转换成std::shared_ptr&lt;T&gt;

编译时如何检查1std::shared_ptr&lt;T&gt;的转换失效?

编译时如何检查1std::nullptr_t的转换失效?

【问题讨论】:

  • 请始终包含您的问题所需的头文件,以使其有意义。我已在您的问题中添加了所需的标题。
  • 这样做是为了保持与早于 C++11 的版本的兼容性,其中 NULL 是 (void *)00 被转换为任何类型的指针。
  • @MarekR:在 C++ 的任何版本中,NULL 都不是 (void *)0;这是 C 标准承认的定义,但 C++ 标准不承认(因为,由于对指针类型的检查更严格,使用起来会变得非常不方便)。
  • @MatteoItalia 不允许 (void *)0 作为空指针值纯粹是一个任意决定。它与“更严格地检查指针类型”无关。承认 (void *)0 为有效的 NULL 可以避免一些但不是所有问题。
  • @curiousguy 是的,考虑一下,已经 0 是分配 和初始化 到指针的特例,我认为没有理由不将其转换为 void *.. . 我想知道为什么他们选择使用普通的 0...

标签: c++ c++11 pointers shared-ptr nullptr


【解决方案1】:

0是 C/C++ 中的一个特殊值。许多事情适用于0,但不适用于1。原因是语言的转换规则。

f1(0); // OK

没关系,因为有以下转换。

0  -> nullptr
nullptr -> std::shared_ptr<bool> // Through a constructor

然而,

f1(1);

不行,因为没有可将1 转换为shared_ptr&lt;bool&gt; 的转换。

【讨论】:

  • 编译时如何检查1std::nullptr_t的转换失效?
  • @chaosink,你必须相信你的编译器会给你一个适当的错误信息。我从 g++ 得到以下信息:error: could not convert ‘1’ from ‘int’ to ‘std::shared_ptr
  • 是的,我相信它。我只想知道编译器如何检测到这个错误?似乎这种检测超出了语言属性。或者它只是标准中的一个项目?所以编译器只是直接实现它?
  • @chaosink,文字0在语言中是特殊的。编译器必须知道如何以不同的方式处理文字 01。请注意,如果您使用int i = 0; f1(i);,您将在使用f1(1); 时收到类似的错误消息。
  • @chaosink 实际上有点糟糕,它不仅仅是文字整数,而是一般的常量整数表达式。 !!!!!!!!!1 必须被编译器识别为有效的空指针值,因此 (1) 可分配给指针类型的任何左值,并且 (2) 可转换为 std::nullptr_t
【解决方案2】:

std::shared_ptr&lt;T&gt; 有一个采用std::nullptr_t 的构造函数,为此存在从任何有效空指针常量的隐式转换,其中包括一个普通的0 文字。另一方面,1 不是任何shared_ptr 构造函数的有效参数。

【讨论】:

  • 编译时如何检查1std::nullptr_t的转换失效?
  • @chaosink 这是什么意思?编译器知道 1 不是有效的空指针常量,因此不考虑转换为 std::nullptr_t,因此您会收到错误消息。
  • 如果问题是,你怎么写像nullptr_t这样的类型,只能从特定的整数值转换,我怀疑答案是“你不能”; nullptr_t 确实很神奇,它需要对核心语言进行一些特殊情况的修改——而不仅仅是修改库——因此。
  • 由编译器实现的临时案例。对于一种语言来说,它是如此的不雅。所以这是另一个例子,展示了现代 C++ 为传统 C++ 带来的沉重负担。
  • 处理 0 有一个空指针常量是 C 的遗留成本,但与许多其他特性相比,成本非常小,例如内置数组表现不佳(不是你可以使用的一流对象) assign) 或其他难以教授的数组规则。
【解决方案3】:

除了其他答案之外,一种解决方法是改用 std::make_shared 宏:

f1(std::make_shared<bool>(0)); // OK
f1(std::make_shared<bool>(1)); // OK

这样您就可以为函数提供任何整数字面量。简单的工作示例:

#include <iostream>
#include <memory>

void f1(std::shared_ptr<bool> ptr) {
    std::cout << std::boolalpha << *ptr << '\n';    
}

int main() {
    f1(std::make_shared<bool>(0)); // OK
    f1(std::make_shared<bool>(1)); // OK
    f1(std::make_shared<bool>(2)); // OK
}

【讨论】:

    猜你喜欢
    • 2015-07-23
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多