草庐IT

c++ - nullptr_t驻留在哪里?

coder 2024-02-04 原文

有点史前史。

我已经写了一段时间的游戏引擎。它分为几个静态库,例如“utils”,“rsbin”(资源系统),“window”,然后链接到一个可执行文件中。

它是一个跨平台引擎,正在针对Windows和Android进行编译。
在Windows下,我使用MinGW进行编译。在Android下,使用CCTools,它是 native gcc的接口(interface)。

基类之一是utils::RefObject,它表示类似于Windows的IUnknown的概念:它提供了一个确定其生存期的引用计数器,以及一种用于从基类指针中查询特定接口(interface)的方法。还有template< typename T > utils::Ref,是专门为此类对象设计的。它持有一个std::atomic< utils::RefObject* >,并在构造,分配和销毁后自动更新其对象的refcount,类似于std::shared_ptr。它还允许通过其查询方法隐式转换不同类型的RefObject。虽然,查询对象的自身类型效率不高,所以utils::Ref重载了其大多数运算符,例如e。 G。有一个特定的utils::Ref< T >::Ref( T* ptr )构造函数,该构造函数仅增加传递的对象的refcount,而一个普通的utils::Ref< T >::Ref( RefObject* ptr ),为T的实例查询其参数,并在失败时引发异常(不过,不用担心,当然,有一种用于软转换的方法)。

但是只有这两种方法会带来一个问题:您不能使用空指针显式初始化utils::Ref,因为它是模棱两可的;因此,还有utils::Ref< T >::Ref( nullptr_t )提供了一种实现方法。

现在,我们正在解决手头的问题。在头文件中,原型(prototype)的拼写与上面完全相同,没有任何前面的std::。请注意,我也不使用using namespace。长期以来,这一直有效。

现在,我正在研究图形系统。它曾经存在过,但是还很初级,所以我什至没有注意到实际上仅定义了OpenGL 1.1,而对于较新的版本,您应该浏览。现在,有必要使用后者。但是包括它破坏了旧的引用类。

从错误消息来看,MinGW现在在原型(prototype)中存在该nullptr_t的问题。我在网上进行了快速搜索,发现通常将其称为std::nullptr_t。虽然不是到处都有。

快速总结:我在没有nullptr_tstd::的情况下编译了using namespace,直到我在 header 之前包含为止。

到目前为止,我一直在使用的网站cplusplus.com/reference建议使用全局::nullptr_t is exactly how it should be。另一方面,en.cppreference.com Wiki tells that实际上是std::nullptr_t

一个快速测试程序,一个带有void foo( int )void foo( nullptr_t )的helloworld,未能编译,并且现在的原因是显式的"error: 'nullptr_t' was not declared in this scope"并建议改用std::nullptr_t

在需要的地方添加std::并不困难;但是这种情况使我颇为好奇。

cplusplus.com实际上在说谎吗? =>以逗号回答,是的。来源不正确。

然后,如果nullptr_t实际上驻留在namespace std中,为什么utils::Ref会编译? =>通过注释中的建议,进行了一些测试,发现包含在其他 header 中的放置在任何stddef header 之前时,定义了全局::nullptr_t。当然不是理想的行为,但这不是主要的错误。无论如何,应该将其报告给MinGW/GCC开发人员。

为什么包含会破坏它? =>如果在之前包含任何stddef header ,则根据标准将类型定义为std::nullptr_t包括,它当然也包括stddef头文件,以及WinAPI所需的其他文件包。

以下是定义相关类的资源:

  • utils/ref.hpp
  • utils/ref.cpp
  • utils/refobject.hpp
  • utils/refobject.cpp
  • utils/logger.hpp =>这个使用互斥量来避免在输出过程中出现线撕裂。
  • utils/cbase.hpp

  • (包括后2个,因此也可能会影响)

    正如评论中所建议的那样,我在已编译的测试用例上运行g++ -E,并在中找到了一个非常有趣的地方:
    #if defined(__cplusplus) && __cplusplus >= 201103L
    #ifndef _GXX_NULLPTR_T
    #define _GXX_NULLPTR_T
      typedef decltype(nullptr) nullptr_t;
    #endif
    #endif /* C++11.  */
    

    现在找到其他地方定义了_GXX_NULLPTR_T的地方...通过MinGW的文件进行的快速GREP除了此stddef.h之外什么都没有找到

    因此,为什么以及如何变得残障仍然是一个谜。尤其是当仅包含时,尽管有一点点,但没有其他地方不会在任何地方定义nullptr_t

    最佳答案

    nullptr的类型在 namespace ::std中定义,因此正确的限定条件是::std::nullptr_t。当然,这意味着您通常在实践中将其拼写为std::nullptr_t

    引用C++ 11:

    2.14.7/1:

    The pointer literal is the keyword nullptr. It is a prvalue of type std::nullptr_t.



    18.2/9:

    nullptr_t is defined as follows:

    namespace std {
      typedef decltype(nullptr) nullptr_t;
    }
    

    The type for which nullptr_t is a synonym has the characteristics described in 3.9.1 and 4.10. [ Note: Although nullptr’s address cannot be taken, the address of another nullptr_t object that is an lvalue can be taken. —end note ]


    <stddef.h>也进入图片。 18.2讨论了<cstddef>,所以这是定义std::nullptr_t的C++ header 。根据D.5/2:

    Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope.



    这意味着包括<stddef.h>可以使您访问::nullptr_t。但是由于这应该是C头文件,所以我建议不要在C++代码中依赖它(即使它在形式上是有效的)。

    关于c++ - nullptr_t驻留在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28696522/

    有关c++ - nullptr_t驻留在哪里?的更多相关文章

    1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

      我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

    2. ruby - 使用 `+=` 和 `send` 方法 - 2

      如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

    3. ruby - 如何计算 Liquid 中的变量 +1 - 2

      我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

    4. ruby-on-rails - ActiveRecord::Associations::CollectionProxy 从哪里获取.each 实例方法? - 2

      假设我有模型Topics和Posts,其中Topichas_many:posts和Postbelongs_to:topic。此时我的数据库中已经有了一些东西。如果我进入Rails控制台并输入Topic.find(1).posts我相信我得到了一个CollectionProxy对象。=>#]>我可以对此调用.each以获得枚举器对象。=>#]:each>我对CollectionProxy如何处理.each感到困惑。我意识到它在某些时候是继承的,但我一直在阅读API文档,他们并没有说得很清楚CollectionProxy是从什么继承的,除非我遗漏了一些明显的东西。Thispage似乎并没有

    5. arrays - Ruby 数组 += vs 推送 - 2

      我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

    6. ruby-on-rails - 闪存消息存储在哪里? - 2

      我以为它们存储在cookie中-但不,检查cookie没有任何结果。session也不存储它们。那么,我在哪里可以找到它们?我需要这个来直接设置它们(而不是通过flashhash)。 最佳答案 它们存储在inyoursessionstore.自rails2.0以来的默认设置是cookie存储,但请检查config/initializers/session_store.rb以检查您是否使用默认设置以外的东西。 关于ruby-on-rails-闪存消息存储在哪里?,我们在StackOverf

    7. += 的 Ruby 方法 - 2

      有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

    8. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

      出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

    9. ruby - Ruby 中字符串运算符 + 和 << 的区别 - 2

      我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc

    10. ruby-on-rails - Ruby 如何知道在哪里可以找到所需的文件? - 2

      这里还有一个新手问题:require'tasks/rails'我在每个Rails项目的根路径中的Rakefile中看到了这一行。我猜这行用于要求vendor/rails/railties/lib/tasks/rails.rb加载所有rake任务:$VERBOSE=nil#LoadRailsrakefileextensionsDir["#{File.dirname(__FILE__)}/*.rake"].each{|ext|loadext}#LoadanycustomrakefileextensionsDir["#{RAILS_ROOT}/lib/tasks/**/*.rake"].so

    随机推荐