【问题标题】:Why are there differences between char* and char[] in case of multiple definition?为什么在多重定义的情况下 char* 和 char[] 有区别?
【发布时间】:2013-04-22 09:08:08
【问题描述】:
  • 在interface.h中定义strInterface

    // interface.h
    #ifndef INTERFACE_H_
    #define INTERFACE_H_
    const char* strInterface = "the difference between char* and char array";
    #endif
    
  • 在 OneUsing 类中,调用 strInterface 字符串

    // oneUsingInterface.h
    #ifndef ONEUSINGINTERFACE_H_
    #define ONEUSINGINTERFACE_H_
    
    class OneUsing
    {
    private:
        int mData;
    public:
        OneUsing();
        OneUsing(int a);
        void print();
    };
    #endif  // ONEUSINGINTERFACE_H_
    
    // oneUsingInterface.cpp
    #include "oneUsingInterface.h"
    #include "interface.h"
    #include <iostream>
    
    using namespace std;
    
    OneUsing::OneUsing()
    {}
    OneUsing::OneUsing(int a)
    {
        mData = a;
    }
    void OneUsing::print()
    {
        cout<<"mData: "<<mData<<" strInterface: "<<strInterface<<endl;
    
    }
    
  • 在main.cpp中,包含interface.h,因为strInterface是直接调用的;它还包括 oneUsingInterface.h,因为将创建 OneUsing 实例。

    //main.cpp
    #include <iostream>
    #include "interface.h"
    #include "oneUsingInterface.h"
    
    using namespace std;
    
    int main()
    {
        cout<<strInterface<<endl;
        OneUsing* pObject = new OneUsing(5);
        pObject->print();
    }
    
  • 现在,问题出现了:

    g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra -c .//main.cpp
    g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra -c .//oneUsingInterface.cpp
    g++ -I../boost_1_52_0/installation/prefix/include -I../boost_1_52_0/installation/prefix/lib -g -Wall -Wextra main.o oneUsingInterface.o -o main
    oneUsingInterface.o:(.data+0x0): multiple definition of `strInterface'
    main.o:(.data+0x0): first defined here
    collect2: error: ld returned 1 exit status
    make: *** [main] Error 1
    
  • 但是,如果 strInterface 是这样定义的,那就没有问题了:

    // interface.h
    #ifndef INTERFACE_H_
    #define INTERFACE_H_
    const char strInterface[] = "the difference between char* and char array";
    #endif
    

在这种情况下,有人能告诉我更多关于char*char[] 之间区别的详细信息吗?

PS:我们经常在头文件中用extern关键字声明全局变量,我们在别人的实现文件中定义它。

【问题讨论】:

    标签: c++ arrays memory-management global-variables multiple-definition-error


    【解决方案1】:

    不同之处在于const char strInterface[] 定义了一个常量。常量对于它们所包含的每个文件都是本地的。您将在每个文件中获得一个单独的副本。

    指针const char* strInterface指向常量数据,但指针本身不是常量。所以默认情况下它对其他翻译单元是可见的。

    【讨论】:

      【解决方案2】:

      默认情况下,声明为const 的命名空间范围变量具有内部链接,因此您可以在多个翻译单元中定义具有相同名称的此类变量而不会导致链接错误。

      这个变量不是const,所以它会有外部链接,这意味着任何程序中只能存在一个这样的定义:

      const char* strInterface = "...";
      

      const 版本是:

      const char* const strInterface = "...";
      

      这是const,因为数组的 const 性与其元素的 const 性之间没有区别。 (IIRC 在标准中对此事实存在一些形式上的歧义。)您可以在程序中的每个翻译单元都有一个这样的定义。

      const char strInterface[] = "...";
      

      【讨论】:

        【解决方案3】:

        这里有两种不同的类型:

        首先,const char* strInterface 是一个指向常量字符的指针,因此您在两个不同的编译单元中的全局范围内创建了一个同名的指针,这使得链接器抱怨这一点。请注意,您可以稍后在代码中使指针指向完全​​不同的东西。指针本身是可变的;它指向的字符串是不可变的。

        其次,const char strInterface[] 是一个常量字符数组,它是为每个编译单元在本地创建的,因此链接器会找到该字符串的多个不冲突的定义。这个常量是不可变的。

        【讨论】:

          猜你喜欢
          • 2022-01-03
          • 1970-01-01
          • 2014-05-03
          • 2020-06-26
          • 2010-12-14
          • 2012-08-14
          • 2010-10-27
          相关资源
          最近更新 更多