在C++中使用execvp的最佳实践

Kev*_*ong 5 c++ execvp

一开始,我写了这样的东西

char* argv[] = { "ls", "-al", ..., (char*)NULL };
execvp("ls", argv);
Run Code Online (Sandbox Code Playgroud)

但是,GCC突然出现了这个警告:"C++禁止将字符串常量转换为char*."

然后,我将代码更改为

const char* argv[] = { "ls", "-al", ..., (char*)NULL };
execvp("ls", argv);
Run Code Online (Sandbox Code Playgroud)

结果,GCC弹出了这个错误,"无效转换const char**为char* const*."

然后,我将代码更改为

const char* argv[] = { "ls", "-al", ..., (char*)NULL };
execvp("ls", (char* const*)argv);
Run Code Online (Sandbox Code Playgroud)

它最终工作,编译没有任何警告和错误,但我认为这有点麻烦,我找不到有人在互联网上写这样的东西.

有没有更好的方法execvp在C++中使用?

Pic*_*ent 5

你遇到了一个真正的问题,因为我们面临两个不兼容的约束:

  1. 一个来自C++标准,要求您必须使用const char*:

    在C中,字符串文字属于类型char[],可以直接分配给(非const)char*.C++ 03也允许它(但不赞成它,因为文字在C++中是const).没有强制转换,C++ 11不再允许这样的赋值.

  2. 另一个来自遗留的C函数原型需要一个(非const)数组char*:

    int execv(const char *path, char *const argv[]);
    
    Run Code Online (Sandbox Code Playgroud)

    因此必须在某个地方进行演员,我找到的唯一解决方案是封装execvp函数.

这是该解决方案的完整运行C++演示.不方便的是你有一些胶水代码可以写一次,但优点是你得到一个更安全和更清晰的C++ 11代码(最后nullptr检查).

#include <cassert>
#include <unistd.h>

template <std::size_t N>
int execvp(const char* file, const char* const (&argv)[N])
{
  assert((N > 0) && (argv[N - 1] == nullptr));

  return execvp(file, const_cast<char* const*>(argv));
}

int main()
{
  const char* const argv[] = {"-al", nullptr};
  execvp("ls", argv);
}
Run Code Online (Sandbox Code Playgroud)

你可以编译这个演示:

g++ -std=c++11 demo.cpp 
Run Code Online (Sandbox Code Playgroud)

您可以在CPP参考示例中std::experimental::to_array看到类似的方法.