vector<T>有一个构造函数,它采用向量的大小,据我所知它是显式的,这可以通过以下代码无法编译的事实证明
void f(std::vector<int> v);
int main()
{
f(5);
}
Run Code Online (Sandbox Code Playgroud)
我无法理解并要求您解释的是以下代码编译的原因
std::vector<std::vector<int>> graph(5, 5);
Run Code Online (Sandbox Code Playgroud)
它不仅编译,它实际上将图形调整为5并将每个元素设置为五个零的向量,即与我通常编写的代码相同:
std::vector<std::vector<int>> graph(5, std::vector<int>(5));
Run Code Online (Sandbox Code Playgroud)
怎么样?为什么?
编译器:MSVC10.0
好吧,似乎这是一个MSVC错误(还有一个).如果有人可以在答案中详细说明错误(即总结复制的情况),我很乐意接受
c++ vector type-conversion explicit-constructor visual-studio
是否可以编写一个类,使其有效:
Foo a;
Foo b = 0;
Foo c = b;
Foo d(0);
Foo e(1);
Foo f = Foo(1);
Run Code Online (Sandbox Code Playgroud)
但这些不是:
int x;
Foo a = x;
Foo b = 1;
Foo c = 2;
//etc
Run Code Online (Sandbox Code Playgroud)
从本质上讲,我的规则是"一个常量0可以隐式转换为a Foo,但没有其他值"
比方说,我们有一流的X与定义的构造X(int value).
这在语义上是否相同?
X x = 42;
X x(42);
Run Code Online (Sandbox Code Playgroud)
我相信只有当我们将显式关键字添加到X的构造函数时才会出现差异.否则编译器会将表达式减少X x = 42;为X x(42);
如果我错了,请纠正我.
我可以使用显式的init-list ctor来确保像{a}这样的表达式不会导致意外的隐式转换吗?而另一个想法:应该我担心呢?写作{a}不太可能是简单的错误a,但另一方面,我们通过隐式转换构建对象的代码仍然可能不清楚.
class Foo
{
explicit Foo (std::initializer_list<Bar> ilist) { /*...*/}
};
Run Code Online (Sandbox Code Playgroud) 任何人都可以解释为什么非单参数构造函数标记为显式编译?据我所知,这里绝对是无用的关键字,为什么这个编译没有错误?
class X
{
public:
explicit X(int a, int b) { /* ... */}
};
Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我不允许声明一个显式的 ctor,因为编译器说我在复制初始化上下文中使用它(clang 3.3和gcc 4.8).我试图通过使ctor非显式,然后将复制构造函数声明为已删除来证明编译器是错误的.
编译器是错误还是有其他解释?
#include <iostream>
template <typename T>
struct xyz
{
constexpr xyz (xyz const &) = delete;
constexpr xyz (xyz &&) = delete;
xyz & operator = (xyz const &) = delete;
xyz & operator = (xyz &&) = delete;
T i;
/*explicit*/ constexpr xyz (T i): i(i) { }
};
template <typename T>
xyz<T> make_xyz (T && i)
{
return {std::forward<T>(i)};
}
int main ()
{
//auto && x = make_xyz(7);
auto && …Run Code Online (Sandbox Code Playgroud) cppreference显示以下定义std::in_place_t:
struct in_place_t {
explicit in_place_t() = default;
};
inline constexpr std::in_place_t in_place{};
Run Code Online (Sandbox Code Playgroud)
他们为什么要添加一个explicit默认的构造函数?为什么不排除它?有什么好处?
在继续阅读本文之前,请阅读复制初始化和直接初始化之间的C++是否存在差异?首先,确保你理解它在说什么.
我先在这里总结一下规则(阅读标准n3225 8.5/16,13.3.1.3,13.3.1.4和13.3.1.5),
1)对于直接初始化,所有构造函数都将被视为重载集,重载决策将根据重载决策规则选择最佳构造函数.
2)对于复制初始化,源类型与目标类型相同或从目标类型派生,规则与上面相同,只是只转换构造函数(没有显式的构造函数)将被视为重载集.这实际上意味着显式复制/移动构造函数不会被视为重载集.
3)对于上面(2)中未包含的复制初始化情况(源类型与目标类型不同而不是从目标类型派生),我们首先考虑可以从源类型转换为目标类型的用户定义转换序列或(当使用转换函数时)到其派生类.如果转换成功,则结果用于指示初始化目标对象.
3.1)在这个用户定义的转换序列中,根据8.5/16和13.3.1.4中的规则,将考虑转换ctors(非显式ctors)和非显式转换函数.
3.2)结果prvalue将直接初始化目标对象,如(1)中列出的规则,见8.5/16.
好吧,对于规则来说,让我们看看一些奇怪的代码,我真的不知道我的推理错在哪里,或者只是所有编译器都错了.请帮帮我,谢谢.
struct A
{
A (int) { }
A() { }
explicit A(const A&) { }
};
struct B
{
operator A() { return 2; }
//1) visual c++ and clang passes this
//gcc 4.4.3 denies this, says no viable constructor available
};
int main()
{
B b;
A a = b;
//2) oops, all compilers deny this
}
Run Code Online (Sandbox Code Playgroud)
在我的理解中,对于(1),
operator A() { return 2; } …Run Code Online (Sandbox Code Playgroud) 我使用 g++ 6.3.0 和 -std=c++14 选项编译了下面的代码。
#include <utility>
#include <iostream>
struct A{
int x;
A(const A&)=default;
A(int x):x(x){}
};
struct B{
A a;
template<class... Args>
B(Args&&... args):a(std::forward<Args>(args)...){
std::cout<<"1!"<<std::endl;
}
explicit B(const A& a):a(a){std::cout<<"2!"<<std::endl;}
};
struct C:B{
using B::B;
};
int main(){
A a{2};
const A& aref=a;
C c=aref; //Implicit conversion
}
Run Code Online (Sandbox Code Playgroud)
我预计它会输出“1!” 因为转换是隐式的,但它输出“2!”。如果我注释掉模板构造函数,它将无法编译。这是正确的行为,还是某种 g++ bug?
我无法弄清楚为什么我的转换运算符正在考虑显式构造函数。
\n#include <utility>\n\ntemplate <typename T = void>\nstruct First\n{\n template <typename... Targs>\n First(Targs&&... args) {}\n};\n\ntemplate <>\nstruct First<void> {};\n\ntemplate <typename T>\nstruct Second\n{\n template <typename... Targs>\n Second(Targs&&... args) {}\n};\n\ntemplate <typename... T> class A;\n\ntemplate <typename SecondType>\nclass A<SecondType>\n{\n public:\n A(const A&) = default;\n explicit A(const First<void>& first) {}\n explicit A(const Second<SecondType>& second) {}\n};\n\ntemplate <typename FirstType, typename SecondType>\nclass A<FirstType, SecondType>\n{\n public:\n A(const First<FirstType> & first) {}\n explicit operator A<SecondType>() const { return A<SecondType>(First<>()); }\n};\n\nint main() {\n A<int, float> a{First<int>(123)};\n A<float> b = static_cast<A<float>>(a);\n\n // test.cpp:41:41: …Run Code Online (Sandbox Code Playgroud)