Why main() in C++ is not overloaded to use std::st

2020-03-08 11:54发布

问题:

I was trying to create a program that takes arguments by command line, using main() function arguments. As a (basic) C++ programmer (even if I know quite well pointers and array in C-style) I hardly ever used char* strings and C-arrays. I spent some to take main() arguments and transform it in std::string... So asked myself: why in C++ the main() function is not overloaded to take an std::vector<std::string> argv instead of the old char* argv[]?

For "overload" I mean the coexistence of main() functions like int main() and int main(int argc, char *argv[]), not the overloading of a normal function made by the programmer.

回答1:

Why isn't it in the standard? Simple:

Because nobody proposed it.

Things go into the C++ standard because someone writes a proposal for it, then gets other people to vote on it and incorporate it. Unless someone actually wants it to happen, it doesn't get to happen.

And considering how trivial this feature really is:

int main(int argc, char **argv)
{
    std::vector<std::string> args(argv, argv + argc);
    ...
}

There just isn't any real need for it. It's a convenience function, and it doesn't even make things that convenient compared to the alternative.



回答2:

why in C++ the main() function is not overloaded to take an std::vector argv instead of the old char* argv[]

Because that demands dependency on <string> library. C++'s philosophy is always "don't pay for what you don't use". If someone doesn't want the automatic memory management offered by string then they can't be enforced.
2nd view: If some platform doesn't have any library support then you cannot start your C++ program!!

On the contrary, int and char** arguments are built-in and independent types. One can always write custom wrapper on main() which does exactly whatever is the need.

Edit: On AProgrammer's comment:
Suppose that main(vector<string>) is allowed; then if a platform conforms to all C++ features, but don't have standard library support then it will become non-standard compliant.



回答3:

The main reason, I suspect, is because the usual implementation is to make it an extern "C" function, with varargs. In a lot of implementations, it is the C runtime library which calls main.

There are many ways around this, but none of them seem worth the bother, given how easy it is to convert the arguments to whatever you want.



回答4:

It would be trivial for a compiler to compile a main defined as

int main(std::vector<std::string> args) {
    ...
}

as it has been written as

int main(int __argc, char **__argv) {
    std::vector<std::string> args(__argv, __argv+__argc);
    ...
}

It would be even about as easy to allow any container, even custom one, and not just std::vector<std::string>. But it isn't standard because ­— standard answer to why isn't this in the standard — nobody proposed it and convinced enough people that it was a good idea. I don't think there was a proposition, so there is probably no rationale for its rejection. The change is probably to simple for most of involved people to bother.



回答5:

Basically, a std::vector is NOT the same (in memory layout or anything) as an array of char *. To permit this, you'd have to make the compiler recognise the new main declaration and add a wrapper on entry that created a vector of strings.

Given you were doing that, you might as well throw argc away as well, and have the declaration of main be

int main(std::vector<std::string> argv)

But it's work for the compiler. You'd have to get a lot of people who thought it was worthwhile.

Otherwise you can just do it yourself

int main(int argc, char **argv)
{
    std::vector<std::string> args;
    args.reserve(argc);
    for (std::size_t arg = 0; arg < argc; ++arg)
    {
         args.push_back(argv[i]);
    }
    return mymain(args);
}

Code is not guaranteed to compile or work cos I just wrote it off the top of my head.

or (better, thanks to AProgrammer)

int main(int argc, char **argv)
{
    return mymain(std::vector<std::string>(argv, argv + argc));
}