将 C 数组传递到一个函数中,该函数需要“动态”的 C 数组,而不定义变量

Passing a C-array into a function which expects a C-array 'on the fly', without defining a variable

提问人:ridilculous 提问时间:4/24/2023 最后编辑:ridilculous 更新时间:4/24/2023 访问量:160

问:

C 存在许多类似的问题,例如这个问题,但我正在寻找 C++ 中最简单、最易读的方法,将 C 数组传递到函数中,而无需先为其定义变量。

给定这些是不可能的(但第一个在 C99 中):void f(double const* a)

f((double []){1,2}); // works in C
f({1,2}); // would be great but doesn't work in any language with C-arrays

当然,首先定义一个变量总是可能的,但这不是我要找的:

double a[] = { 1.2, 3.4 };
f(a);

但是,可以将事物包装成一个结构体,例如

struct A { double a[2]; };
f(A{2.3,4.5}.a);

而且这种类型可以重复使用,所以这已经是一个小小的胜利了

现场演示

但这仍然感觉很笨拙。

有没有更简单、更易读的方法?在当前标准之一中,或者在即将到来的标准中?

编辑:对不起,我之前没有提到过;我无法更改目标 API。应提供指向双精度的指针。

C++ 数组 函数 参数传递

评论

3赞 gsamaras 4/24/2023
“所以这已经是一个小小的胜利了”。为谁赢?当然不是为了下一个阅读你的代码的人。
0赞 Pete Becker 4/24/2023
在第一个示例中,是指向 的指针,而不是指向 的发布者。这不可能匹配。double *[]doubledouble
0赞 ridilculous 4/24/2023
@churill true,但在这种情况下我无法更改目标 API
0赞 ridilculous 4/24/2023
@PeteBecker 如果您指的是第一个示例,那么这就是我链接的有关 C 版本的问题中的代码。我没有更改该代码,但为了完整性而添加了它。如果我删除它或添加一个标题表明它来自 C 问题,这个问题会更直观吗?f((double *[]){1,2});
1赞 Scheff's Cat 4/24/2023
我相信你把事情搞糊涂了。您链接的 C 问题旨在解决字符串数组,即 s 数组。因此,这是有道理的。如果你试图解决一个s数组,是完全错误的 - 在C和C++中。此外,我不认为在这里引用 C 没有多大价值。C 和 C++ 是不同的语言,其中一种语言是正确的,对另一种语言来说并不一定意味着什么。charchar *[]doubledouble *[]

答:

3赞 Michael Kopp 4/24/2023 #1

你用 a 代替 怎么样?然后,即使在呼叫站点,您也可以就地构建一个,如下所示:vectordouble*

#include<vector>

double f(std::vector<double> const& v)
{
  return v[0];
}


int main()
{
  f({1,2,3});
}
1赞 cptFracassa 4/24/2023 #2

如果你能用 c++20 编译,那么显而易见的答案就是使用 std::span,以获得最大的灵活性。

演示:

#include <array>
#include <span>
#include <vector>

void f(std::span<const double> a);

int main()
{
    f({{1.0, 2.0, 3.3}});

    double ca[] = { 1.2, 3.4 };
    f(ca);

    std::vector<double> v = { 1.2, 3.4 };
    f(v);

    std::array a = { 1.2, 3.4 };
    f(a);
}
1赞 NathanOliver 4/24/2023 #3

如果要避免动态分配,请使用 std::initializer_list

template <typename T>
void f(const std::initializer_list<T>& v)
{
    for (const auto& e : v)
        std::cout << e << " ";
    std::cout << "\n";
}


int main()
{
    f({1,2,3});
    f({4.0,5.1,6.2});
}

输出

1 2 3 
4 5.1 6.2 

现场示例

6赞 Artyer 4/24/2023 #4

此功能非常适合:

template<typename T, std::size_t N>
constexpr T* temporary_array(T(&& arr)[N]) noexcept { return arr; }

然后,您只需调用(或)。f(temporary_array<double>({1,2}));f(temporary_array({1., 2.}))

在 C++20 中,您可以编写 . 也应该适用于任何 C++ 版本,但 GCC 有一个长期存在的错误,不允许编译它。f(std::type_identity_t<double(&&)[]>{1,2})f(std::type_identity_t<double[]>{1, 2})

寻找标准库解决方案,您可以替换为 .写出 size 参数很烦人,但可以用 CTAD 替换:struct Astd::array<double, 2>

f(std::array{ 1., 2. }.data());
f(std::array<double, 2>{1, 2}.data());
// (These will call move constructors)
f(std::to_array<double>({1, 2}).data());
f(std::to_array({1., 2.}).data());