我有这个简单的代码,编译时没有错误/警告:
void f(int&, char**&){}
int main(int argc, char* argv[])
{
f(argc, argv);
return 0;
}
下一个不编译的类似代码:
void f(int&, char**&){}
int main()
{
int argc = 2;
char* argv[] = { "", "", nullptr };
f(argc, argv);
//@VS2013 error: cannot convert argument 2 from 'char *[3]' to 'char **&'
//@GCC error: invalid initialization of non-const reference of type 'char**&' from an rvalue of type 'char**'
return 0;
}
为什么char*[]
可以在第一个样本中转换为char**&
而在第二个样本中无法转换?如果在编译时知道大小是否重要?
编辑:我认为在第二种情况下需要进行2次转换,编译器只能进行一次隐式转换。
此代码编译良好:
void f(int&, char**&){}
int main()
{
int argc = 2;
char* temp[] = { "", "", nullptr };
char** argv = temp;
f(argc, argv);
return 0;
}
答案 0 :(得分:9)
因为尽管出现了main
的第二个参数
输入char**
。用作函数的声明时
参数,顶级数组被重写为指针,因此char
*[]
实际上是char**
。这仅适用于功能
然而,参数。
char*[]
(如第二种情况)可以转换为char**
,
但是转换的结果(与任何转换一样)是一个
rvalue,不能用于初始化非const引用。
你为什么要参考?如果是修改指针,
将char**
参数修改为main
是未定义的行为
(正式地,在C中,至少 - 我没有检查过C ++是否更多
自由派在这里)。当然,你没办法
修改数组的常量地址。如果你不想要的话
要修改它,为什么要使用引用?
答案 1 :(得分:3)
Jefffrey's comment引用标准,现在是:
4.2数组到指针的转换[conv.array]
可以转换“N T数组”或“T未知数组”的左值或右值 到“指向T的指针”的prvalue。结果是指向的指针 数组的第一个元素。
prvalue是:
prvalue(“纯”rvalue)是一个标识临时值的表达式 对象(或其子对象)或者是与any无关的值 对象
您不能将非const引用绑定到临时引用。
int& i = int(); // error
char* argv[] = { "", "", nullptr };
// the result of the conversion is a prvalue
char**& test = argv; // error
因此,以下代码将很乐意编译:
#include <iostream>
void f(int& argc, char** const& argv){
std::cout << argv[0] << std::endl; // a
}
int main()
{
int argc = 2;
char* argv[] = { "a", "b", nullptr };
f(argc, argv);
return 0;
}
我在Kanze's comment中指出了一件重要的事情。
在OP中提供的第一个示例中,char* argv[]
和char** argv
是等效的。因此,没有转换。
std::cout << std::is_array<decltype(argv)>::value << std::endl; // false
std::cout << std::is_array<char**>::value << std::endl; // false
std::cout << std::is_array<char*[]>::value << std::endl; // true
std::cout << std::is_same<decltype(argv), char**>::value << std::endl; // true
std::cout << std::is_same<decltype(argv), char*[]>::value << std::endl; // false
答案 2 :(得分:0)
中
temp
的类型
char* temp[] = { "", "", nullptr };
不 char * [],它是
char*[3]
后者不能隐式转换为`char **'。
在main
中,argv
的类型是未绑定的char*
数组,相当于char**
我承认,这令人困惑:)