【问题标题】:C++ empty String constructorC++ 空字符串构造函数
【发布时间】:2009-05-29 11:18:22
【问题描述】:

我是 C++ 初学者,如果问题太基本,请见谅。

我已经尝试收集字符串 constrcturs 并尝试所有它们(以记住它们)。

string strA();          // string(); empty string // incorrect
string strB("Hello");   // string( const char* str)
string strC("Hello",3); // string( const char* str, size_type length)
string strD(2,'c');     // string( size_type lenght, const char &c)
string strE(strB);      // string( const string& s)

cout << strA << endl;
cout << strB << endl;
cout << strC << endl;
cout << strD << endl;
cout << strE << endl;

除了 strA 之外,所有这些都有效。它打印“1”。 为什么?在这种情况下 strA 的类型是什么?当我不确定时如何检查物品的类型?

我注意到正确的方法是这样(顺便说一句,这似乎与其他构造函数不一致,有时parens有时没有parens):

string strA;

ps:粗体问题,通常不相关的答案将被否决。

【问题讨论】:

    标签: c++ string


    【解决方案1】:

    这是一个非常受欢迎的问题。 C++ 语法是模棱两可的。解决歧义的规则之一是“如果某件事看起来像声明,那就是声明”。在这种情况下,您声明了一个函数原型,而不是定义一个变量。

    string strA();
    

    等价于

    string strA(void);
    

    返回字符串的无参数函数原型。

    如果你想显式调用无参数构造函数,试试这个:

    string strA=string();
    

    它并不完全等价——它的意思是“使用无参数构造函数创建一个临时字符串,然后将其复制以初始化变量 strA”,但允许编译器对其进行优化并省略复制。

    编辑: Here is an appropriate item in C++ FAQ Lite

    【讨论】:

    • 这也是我停止使用 C++ 的原因之一。
    • @Dietrich Epp:这也困扰着我。我想这是为保持 C 兼容性而付出的代价。另一种选择是使用 C,它有很多问题,我的猜测是最好保留 C++ 并避免这种陷阱。
    • std::string strA("");怎么样
    【解决方案2】:

    它认为

    string strA();
    

    作为函数声明。

    对于默认构造函数使用:

    string strA;
    

    【讨论】:

    • 在堆外分配时可以使用该符号:string* strA = new string();
    【解决方案3】:

    在 C++ 中,就像在 C 中一样,有一条规则规定任何看起来像声明的东西都将被视为声明。

    string strA();
    

    看起来像一个函数声明,所以它被视为一个。你需要:

    string strA;
    

    【讨论】:

      【解决方案4】:

      我认为在这种情况下,“如果可以是声明,则视为声明”的规则不适用。因为在下文中,两者都是声明

      string a;
      string a();
      

      一个是对象的声明,一个是函数的声明。该规则适用于其他情况。例如,在这种情况下:

      string a(string());
      

      在这种情况下,string() 可能意味着两件事。

      • 未命名函数参数的声明
      • 创建默认构造string的表达式

      这里也适用,string()的意思和下面的一样,命名参数(在声明函数时,名称与参数无关)

      string a(string im_not_relevant());
      

      如果函数将数组或另一个函数作为参数,则该参数会衰减为指针。在函数参数的情况下,指向函数的指针。因此,它等价于以下,可能看起来更熟悉

      string a(string (*im_not_relevant)());
      

      但在你的情况下,它是进入方式的语法。就是说下面是一个函数声明。它永远不能是一个对象的声明(即使这可能是程序员的意图!)

      string a();
      

      所以首先在这个上下文中没有歧义,因此它声明了一个函数。由于string 有一个用户定义的构造函数,您可以省略括号,效果与预期相同。

      【讨论】:

        【解决方案5】:

        它打印1,因为指向函数的指针总是转换为数字,如@9​​87654322@。

        【讨论】:

        • 仅当指向函数的指针不为空时。无论如何,指向函数的指针应该指向它的定义,而这里没有。这不应该链接。
        【解决方案6】:

        tkopec 关于它为什么不起作用的原因是正确的。要回答您的第二个问题,请按以下方式检查类型:

        template<typename TEST> void Error_() {
           TEST* MakeError = 1;
        }
        

        调用Error_(StrA);你会得到一个编译错误,你的编译器可能会告诉你它发生在Error_&lt; std::basic_string&lt;char, std::allocator&lt;char&gt; &gt; (*)(void)&gt;(std::basic_string&lt;char, std::allocator&lt;char&gt; &gt; (*)(void)) 现在,std::basic_string > 只是 std::string,所以这真的意味着Error_&lt; std::string (*)(void)&gt; (std::string (*)(void))。 '' 之间的部分在'()' 之间重复,这就是strA 的类型。在这种情况下,std::string (*)(void)

        【讨论】:

        • strA 的类型是一个函数。 std::string(void) 。它不是函数指针。他必须将其声明为字符串 (*strA)();如果他希望它是一个函数指针。我可能知道你的意思,但你的最后几句话听起来像你说的是一个函数指针。
        【解决方案7】:

        编译器将string strA() 解释为函数的函数原型,该函数接受void 参数并返回字符串类型的对象。如果要创建一个空字符串对象,请使用string strA;(不带括号)

        【讨论】:

          猜你喜欢
          • 2020-04-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-20
          • 2012-09-07
          • 2014-11-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多