【问题标题】:c++ string array initializationc++ 字符串数组初始化
【发布时间】:2012-03-08 23:29:41
【问题描述】:

我知道我可以在 C++ 中做到这一点:

string s[] = {"hi", "there"};

但是有没有办法在不删除 string s[] 的情况下以这种方式删除数组?

例如

void foo(string[] strArray){
  // some code
}

string s[] = {"hi", "there"}; // Works
foo(s); // Works

foo(new string[]{"hi", "there"}); // Doesn't work

【问题讨论】:

  • 为什么要使用动态分配的 c 样式数组?我建议您改用std::vector。使用 c++11 时,您可以使用初始化列表来构造它们,例如void foo(vector<string>); foo({"hi", "there"}); 应该在 c++11 中工作

标签: c++ arrays string initialization


【解决方案1】:

在 C++11 中可以。事先说明:不要new数组,没有必要。

首先,string[] strArray 是一个语法错误,应该是 string* strArraystring strArray[]。而且我认为这只是为了示例,您没有传递任何大小参数。

#include <string>

void foo(std::string* strArray, unsigned size){
  // do stuff...
}

template<class T>
using alias = T;

int main(){
  foo(alias<std::string[]>{"hi", "there"}, 2);
}

请注意,如果您不需要将数组大小作为额外参数传递会更好,幸好有一种方法:模板!

template<unsigned N>
void foo(int const (&arr)[N]){
  // ...
}

请注意,这只会匹配堆栈数组,例如int x[5] = ...。或者临时的,通过使用上面的alias 创建。

int main(){
  foo(alias<int[]>{1, 2, 3});
}

【讨论】:

    【解决方案2】:

    在 C++11 之前,您不能使用 type[] 来初始化数组。但是最新的 c++11 提供(统一)初始化,所以你可以这样做:

    string* pStr = new string[3] { "hi", "there"};
    

    http://www2.research.att.com/~bs/C++0xFAQ.html#uniform-init

    【讨论】:

      【解决方案3】:

      有了对 C++11 初始化列表的支持,这很容易:

      #include <iostream>
      #include <vector>
      #include <string>
      using namespace std;
      
      using Strings = vector<string>;
      
      void foo( Strings const& strings )
      {
          for( string const& s : strings ) { cout << s << endl; }
      }
      
      auto main() -> int
      {
          foo( Strings{ "hi", "there" } ); 
      }
      

      缺少这些(例如对于 Visual C++ 10.0),您可以执行以下操作:

      #include <iostream>
      #include <vector>
      #include <string>
      using namespace std;
      
      typedef vector<string> Strings;
      
      void foo( Strings const& strings )
      {
          for( auto it = begin( strings );  it != end( strings );  ++it )
          {
              cout << *it << endl;
          }
      }
      
      template< class Elem >
      vector<Elem>& r( vector<Elem>&& o ) { return o; }
      
      template< class Elem, class Arg >
      vector<Elem>& operator<<( vector<Elem>& v, Arg const& a )
      {
          v.push_back( a );
          return v;
      }
      
      int main()
      {
          foo( r( Strings() ) << "hi" << "there" ); 
      }
      

      【讨论】:

      • 过于冗长:使用基于范围的循环:for(auto s : strings) cout &lt;&lt; s &lt;&lt;endl;
      • @rwst:是的,今天就是这样。谢谢。我可能在 2012 年使用迭代器来支持常见的 Visual C++。您展示的简单循环在复制字符串时效率稍低,但 (1) 与循环体中的 io 和 (2) 相比微不足道) 无论如何都无关紧要,因为这不是本示例的内容,并且 (3) 为提高效率而重写(不教坏习语)并不难理解。因此,截至 2015 年,我认为没有理由保留我使用的迭代器循环。随意修复。 :)
      • @rwst:好的,我自己更新了。还检查了 Visual C++ 10 示例是否实际使用 VC10 编译。当我现在看它时,我不记得 VC10 支持右值引用,但是它确实支持(至少代码编译并产生了正确的结果)。
      • using Strings = vector&lt;string&gt;typedef vector&lt;string&gt; Strings 非常不需要,让阅读代码变得更加困难
      【解决方案4】:

      在 C++11 及更高版本中,您还可以使用初始化列表初始化 std::vector。例如:

      using namespace std; // for example only
      
      for (auto s : vector<string>{"one","two","three"} ) 
          cout << s << endl;
      

      因此,您的示例将变为:

      void foo(vector<string> strArray){
        // some code
      }
      
      vector<string> s {"hi", "there"}; // Works
      foo(s); // Works
      
      foo(vector<string> {"hi", "there"}); // also works
      

      【讨论】:

        猜你喜欢
        • 2022-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-08
        • 2011-12-11
        • 1970-01-01
        • 2014-10-16
        相关资源
        最近更新 更多