有没有办法在 C++ 中将匿名数组作为参数传递?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1140630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there any way to pass an anonymous array as an argument in C++?
提问by Jeremy Friesner
I'd like to be able to declare an array as a function argument in C++, as shown in the example code below (which doesn't compile). Is there any way to do this (other than declaring the array separately beforehand)?
我希望能够在 C++ 中将数组声明为函数参数,如下面的示例代码所示(无法编译)。有没有办法做到这一点(除了事先单独声明数组)?
#include <stdio.h>
static void PrintArray(int arrayLen, const int * array)
{
for (int i=0; i<arrayLen; i++) printf("%i -> %i\n", i, array[i]);
}
int main(int, char **)
{
PrintArray(5, {5,6,7,8,9} ); // doesn't compile
return 0;
}
回答by rlbond
If you're using older C++ variants (pre-C++0x), then this is not allowed. The "anonymous array" you refer to is actually an initializer list. Now that C++11 is out, this can be done with the built-in initializer_list
type. You theoretically can also use it as a C-style initializer list by using extern C
, if your compiler parses them as C99 or later.
如果您使用的是较旧的 C++ 变体(C++0x 之前的版本),则不允许这样做。您所指的“匿名数组”实际上是一个初始化列表。现在 C++11 出来了,这可以用内置initializer_list
类型来完成。理论上extern C
,如果您的编译器将它们解析为 C99 或更高版本,您也可以通过 using 将其用作 C 风格的初始值设定项列表。
For example:
例如:
int main()
{
const int* p;
p = (const int[]){1, 2, 3};
}
回答by Adam Rosenfield
It's allowed with a typecast in C++11 and in extern "C"
with C99:
在 C++11 和extern "C"
C99 中允许使用类型转换:
void PrintArray(size_t len, const int *array)
{
for(size_t i = 0; i < len; i++)
printf("%d\n", array[i]);
}
int main(int argc, char **argv)
{
PrintArray(5, (const int[]){1, 2, 3, 4, 5});
return 0;
}
回答by niteria
This compiles, but I wouldn't recommend it.
这可以编译,但我不推荐它。
#include <stdio.h>
struct arr
{
int array[5];
};
static void PrintArray(int arrayLen, arr array)
{
for (int i=0; i<arrayLen; i++) printf("%i -> %i\n", i, array.array[i]);
}
int main(int, char **)
{
PrintArray(5, (arr){5,6,7,8,9});
return 0;
}
回答by ovanes
Disclaimer: For this answer I get some downvotes, but it originates from 2009, where C++ 11 was about to be defined. For modern C++ please scroll below.
免责声明:对于这个答案,我得到了一些反对,但它起源于 2009 年,当时 C++ 11 即将被定义。对于现代 C++,请在下方滚动。
Well, try using boost...
好吧,尝试使用增强...
Here is the solution using the boost::assign library and bit more C++ like programming ;)
这是使用 boost::assign 库和更多类似 C++ 的编程的解决方案;)
#include <boost/assign/list_of.hpp>
#include <iostream>
#include <algorithm>
namespace
{
template<class CollectionT>
void print(CollectionT const& coll)
{
std::ostream_iterator<int> out(std::cout, ", ");
std::copy(coll.begin(), coll.end(), out);
}
}
int main()
{
using namespace boost::assign;
print( list_of(1)(2)(3)(4)(5) );
return 0;
}
C++ 11 and higher with the explanation of particular features
C++ 11 及更高版本,并附有对特定功能的解释
Complied with clang:
clang++ -std=c++14 -I /usr/local/include/ main.cpp
符合叮当:
clang++ -std=c++14 -I /usr/local/include/ main.cpp
#include <boost/assign/list_of.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <initializer_list>
template<typename CollectionT, typename OStream>
auto // <- auto result type deduction from C++ 14
make_output_iterator(CollectionT const& coll, OStream& out)
{
return std::ostream_iterator<typename CollectionT::value_type>(out, ", ");
}
// here template specialization is used, to demonstrate initializer lists from C++ 11
template<typename T>
void print(std::initializer_list<T> items)
// ^----------------------^ passed by value due to move semantics
{
using namespace std;
cout << "printing an initializer list: ";
copy(items.begin(), items.end(), make_output_iterator(items, cout));
cout << endl;
}
template<typename CollectionT>
void print(CollectionT const& items)
{
using namespace std;
cout << "printing another collection type: ";
copy(items.begin(), items.end(), make_output_iterator(items, cout));
cout << endl;
}
int main()
{
print({0,1,2,3,4,5,6,7,9});
using namespace boost::assign;
print( list_of(0)(1)(2)(3)(4)(5)(6)(7)(8)(9) );
}
回答by Michael Aaron Safyan
Yes and no. In the current version of the standard (ISO C++ 1998 with ammendments from 2003), it is not possible. However, in the next version of the standard "C++0x" (which, despite its name implying that it will be released in 200x, will most likely be released in 2010), it will be possible with std::initializer_list<>.
是和否。在标准的当前版本(ISO C++ 1998 和 2003 年的修订版)中,这是不可能的。然而,在标准“C++0x”的下一个版本中(尽管它的名字暗示它将在 200x 中发布,但很可能会在 2010 年发布),使用 std::initializer_list<> 是可能的.
回答by Joe D
With C++0x you could use an std::initializer_list
(and a foreach loop)
使用 C++0x,您可以使用一个std::initializer_list
(和一个 foreach 循环)
#include <iostream>
#include <initializer_list>
void print (const std::initializer_list<int>& array)
{
for (auto x : array) // C++0x foreach loop
std::cout << x << std::endl;
}
int main (int argc, char ** argv)
{
print ({ 1, 2, 3, 4, 5 });
}
回答by Ruslan
Starting from C++11, you can just use std::begin(std::initializer_list const&)
to get the pointer. Example:
从 C++11 开始,您可以使用std::begin(std::initializer_list const&)
来获取指针。例子:
#include <iostream>
void func(int len, const int* x)
{
for(int i=0;i<len;++i)
std::cout << x[i] << "\n";
}
int main()
{
func(5, std::begin({1,3,6,823,-35}));
}
Unlike the accepted answer, this is really Standard-compatible code.
与接受的答案不同,这确实是与标准兼容的代码。
回答by prewett
You can use std::initializer_list list Joe D suggests, however I am not sure you can use it if you want other parameters. (I can't seem to find any information on that.) However, if you declare a const reference to a vector, the initializer_list that is created with { ... } will get converted to the vector.
您可以使用 std::initializer_list 列表 Joe D 建议,但是如果您想要其他参数,我不确定您是否可以使用它。(我似乎找不到任何相关信息。)但是,如果您声明对向量的 const 引用,则使用 { ... } 创建的 initializer_list 将被转换为向量。
#include <iostream>
#include <vector>
void PrintArray(const char* prefix, const std::vector<int>& array)
{
std::cout << prefix << std::endl;
for (int i : array) {
std::cout << i << std::endl;
}
}
int main(int, char **)
{
PrintArray("test array", {5,6,7,8,9} );
return 0;
}
回答by Darryl
You could use a variable number of arguments instead of passing an array:
您可以使用可变数量的参数而不是传递数组:
static void PrintArray(int arrayLen, ...)
{
int this_value;
va_list array;
va_start(array, arrayLen);
for (int i=0; i<arrayLen; i++)
{
this_value = va_arg(array, int);
printf("%i -> %i\n", i, this_value);
}
va_end(array);
}
I didn't compile this so I probably made a mistake or two, but hopefully it's close enough. Look up va_start for reference.
我没有编译这个,所以我可能犯了一两个错误,但希望它足够接近。查找 va_start 以供参考。
回答by Darryl
Another choice would be to use array in the TR1 library which is likely to become part of the next standard and is supported by many compilers.
另一种选择是在 TR1 库中使用数组,它很可能成为下一个标准的一部分,并得到许多编译器的支持。
#include <array>
#include <algorithm>
#include <iostream>
using std::tr1::array;
using std::cout;
using std::copy;
using std::ostream_iterator;
template <class Container>
void PrintArray(Container &values)
{
copy(values.begin(), values.end(), ostream_iterator<int>(cout, "\n"));
}
int main()
{
array<int, 5> values = {1, 2, 3, 4, 5};
PrintArray(values);
}