C++字符串数组初始化

29

我知道可以用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

3
为什么要使用动态分配的C风格数组?我建议你使用std::vector。在使用C++11时,你可以使用初始化列表来构造它们。例如,void foo(vector<string>); foo({"hi", "there"}); 应该在C++11中起作用。 - Grizzly
4个回答

19
在C++11中,你可以这样做。提前注意:不要使用new创建数组,没有必要。
首先,string[] strArray是语法错误,应该是string* strArray或者string 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});
}

10

4

支持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" ); 
}

1
过于冗长:使用基于范围的循环:for(auto s : strings) cout << s <<endl; - rwst
@rwst:是的,今天是这样。谢谢。我可能在2012年使用迭代器来支持常见的Visual C++。你展示的简单循环有一点低效,因为它复制字符串,但(1)与循环体中的io相比,这是微不足道的,而且(2)它与本例无关,(3)为了提高效率(而不是教坏习惯),重写并不难理解。所以,截至2015年,我认为没有理由保留我使用的迭代器循环。请随意修正。 :) - Cheers and hth. - Alf
@rwst:好的,我自己更新了。我还检查了一下Visual C++ 10示例是否可以在VC10上编译。当我现在看它时,我不记得VC10支持右值引用,但是它确实支持(至少代码可以编译并产生正确的结果)。 - Cheers and hth. - Alf
"using Strings = vector<string>" 和 "typedef vector<string> Strings" 非常不必要,而且会让代码阅读起来更加困难。 - Piotr Dobrogost

2
在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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接