【问题标题】:Why can't objects of type void be created in C++?为什么不能在 C++ 中创建 void 类型的对象?
【发布时间】:2011-07-22 17:44:28
【问题描述】:

C++ 不允许创建void 类型的对象。这是为什么呢?

【问题讨论】:

  • 强制性时空物理笑话放在这里。
  • 好吧,你知道什么是“空”吗?那就是“无”,你怎么能什么都没有呢?开个玩笑。
  • @Shuo:这是一个非常好的答案。

标签: c++ types void


【解决方案1】:

考虑下面的代码。

class Foo
{
    // etc ...
};

int main()
{
    // Declaring an object...
    Foo foo;
    // foo has been created.

    // etc ...

    return 0; // When function returns, foo will be destroyed.
}

为了知道如何实际创建对象,编译器必须知道类型。非正式地,您可以将void 视为表示没有类型的“类型”。因此,编译器不可能知道如何创建void 对象。你不能创建一个你不知道如何创建的对象。

int main()
{
    void v; // "I don't know how to create this!"
}

话虽如此,在其他情况下void 是有意义的。例如,void 函数没有返回值。您不能为不存在的事物(如返回值)分配类型。

您还可以拥有指向voidvoid* 的指针。与普通的void 不同,void* 是有效的,并且仅表示“指向某个未知类型对象的指针”。显然,在将 void* 转换为实际的已知类型之前,您不能做太多事情(当然,假设转换是安全的)。

【讨论】:

  • 这在概念上是正确的,但在规范方面并不准确。 void 肯定是一个类型,它只是一个不完整的类型,代表一组空值。
  • 我对这个描述不满意。对于像int 这样的内置类型也是如此:它没有构造函数也没有析构函数,但编译器很高兴地允许创建它的对象。总之,这个答案是错误的。
  • @Konrad Rudolph 我一直认为内置类型具有构造函数,这就是我可以执行“int x(4)”的原因。
  • @MeThinks 它们支持类似构造函数的语法,但它们没有构造函数,只有初始化器。
  • @Konrad Rudolph 非常感谢。所以在这种情况下,如果它看起来像鸭子,叫起来像鸭子;然后它非常像鸭子,但不一定是鸭子。刚刚看到标准说构造函数(成员函数)必须在类中定义,并且内置类型不是类。所以毕竟只是语法糖:)
【解决方案2】:

void 是一个占位符,表示不需要任何类型的对象

作为函数参数说明

过去,C 在函数声明 ala return_type f(); 中使用空参数列表来允许调用 f(),但在每个调用站点都指定了许多和任何类型的参数,而 return_type f(void); 明确表示没有参数是预期的或允许的。 IE。 C 已准备好相信程序员能够正确获取参数的数量和类型,任何错误都可能损坏数据和/或使程序崩溃。

作为函数返回类型

如果void 没有建立作为语言语法一部分的整体“类型变量|函数”序列,那么语言中也会出现一些歧义。例如:

f();  // declaration of a function that returns nothing?
      // OR a function call?

与其他类型的比较

它本身并不是真正意义上的数据类型,它表示对内存区域的某种解释,如 int、float、char 等、类、联合等。

指向无效的指针

对于void*,它表示对包含地址的内存内容失去了洞察力,因此在取消引用指针之前,必须将其强制转换为反映该内存地址处数据按位布局的特定类型。然后,编译器可以根据当时已知的数据类型解释和操作该位布局。

【讨论】:

    【解决方案3】:

    附带说明,您可以创建一个 void 类型的临时对象:

    void f()
    {
        return void();
    }
    
    void g()
    {
        return cout << "hi", f();
    }
    

    这是有效的代码。它在通用代码中非常有用。它甚至被认为允许在某些地方(如基类)使用内置类型(包括 void):

    template<class T> class A : T { };
    
    A<string> x; // works
    A<int> y; // error, but could be usefull
    A<void> z; // error, but could be usefull.
    

    【讨论】:

    • 这真的是标准用语中的暂时性吗?那么标准会包含一个矛盾:C++ 中的一个对象被定义为一个大小为 != 0 的内存位置,所以上面的 不能 是一个对象。
    • return cout &lt;&lt; "hi", f(); 中没有临时 void 对象。这个表达式的意思是“在 cout 和 "hi" 上调用 operator void foo() {} void bar() { return foo(); } - 这有效,但从来没有任何临时对象,根本没有任何东西返回。
    • 我认为这不是暂时的。我认为它利用了标准中的一堆特殊情况例外。 (1) void 函数可以将 return 与 void 表达式一起使用,(2) void() 是 void 表达式,not 构造函数调用不完整的类型,正如您通过查看所想的那样在它。但是,这些异常的目的是使其 看起来 就好像返回了一个“void object”。正如 ybungalobill 所说,它有助于编写泛型。但是尝试使用const 引用那个似乎是暂时的东西,看看你能走多远(8.2.3/4);-)
    【解决方案4】:

    这是因为void是一个不完整的类型。

    来自标准文档,不完整类型 3.9 指出,

    5 已声明但未定义的类,或大小未知或元素类型不完整的数组,是 未完全定义的对象类型。38) 未完全定义的对象类型和 void 类型是不完全类型 (3.9.1)。 对象不应被定义为具有不完整的类型。

    38) 不完全定义的对象类型实例的大小和布局未知。

    由于void是一个不完整的类型,它的大小和布局无法确定,因此无法定义。

    【讨论】:

      【解决方案5】:

      这只是 C 的任意决定。

      在 C 中,所有类型(void 除外)都用于携带值。 void,根据定义,没有任何价值。因此,语言设计者决定无法实例化它。

      C++ 追随 C,决定依然存在。否则就必须定义存储大小(可能与bool 相同)。

      在 C++ 中确实很烦人,尤其是因为模板类/函数所需的特殊大小写,但没有人认为它值得修改,因为可以为 void 专门化模板,因此它不会阻塞。

      【讨论】:

        【解决方案6】:

        void代表Nothing。即使你用Void类型创建函数我们也不需要返回一个值。和Here一样也没有声明void类型的对象。

        【讨论】:

          【解决方案7】:

          C++ 中,每件事都可以与对象相关联。所以,当说-

          void variable ;  
          

          平台必须在不知道其类型的情况下为variable 分配多少字节。是intfloat 还是double 或任何其他原始类型。所以,这是不允许的。

          【讨论】:

          • 虽然这只是 B.S.忘记定义(或者故意没有定义,因为他认为它没用,谁知道)。没有紧迫的理由必须这样做。例如 gcc 有 sizeof(void) == 1。它确实在启用警告的情况下发出警告,但它工作得很好。当然,它存在的原因并不是有人真的想使用它,它的存在只是为了保持一致性,因为定义了 void 指针的算术运算,而且 gcc 家伙认为,如果你可以增加指针类型,你必须能够也查询其值的大小。
          • 作为一个有趣的轶事,出于类似的原因(“使指针和获取地址工作”),空结构的大小为 1。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-10
          相关资源
          最近更新 更多