为什么当我用大括号初始化 std::vector 时
std::vector<TS> vec {ts1, ts2};
Run Code Online (Sandbox Code Playgroud)
编译器调用两次复制构造函数运算符?另一方面 - 使用push_back它只调用一次。
#include <iostream>
#include <vector>
using namespace std;
struct TS{
TS(){
cout<<"default constructor\n";
}
TS(const TS &other) {
cout<<"Copy constructor\n";
}
TS(TS &&other) noexcept{
cout<<"Move constructor\n";
}
TS& operator=(TS const& other)
{
cout<<"Copy assigment\n";
return *this;
}
TS& operator=(TS const&& other) noexcept
{
cout<<"Move assigment\n";
return *this;
}
~TS(){
cout<<"destructor\n";
}
};
int main() {
TS ts1;
TS ts2;
cout<<"-----------------------------------------\n";
std::vector<TS> vec {ts1, ts2};
//vec.push_back(ts1);
//vec = {ts1, ts2};
cout<<"-----------------------------------------\n";
return …Run Code Online (Sandbox Code Playgroud) struct A
{
private:
int a, b, c;
};
int main()
{
A a1{};
A a2 = {};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该代码由VC++ 2012编译(最新更新"2012年11月CTP").
我希望a1和a2是零初始化的,但不是.a1和a2未初始化.
为什么?
我正在尝试初始化类型的对象:
template<typename T>
struct thing : std::array<std::array<T, 2>, 2>
{
};
thing<int> t1 {{ {1,2}, {3,4} }};
Run Code Online (Sandbox Code Playgroud)
我明白了:
error: no matching function for call to ‘thing<int>::thing(<brace-enclosed initializer list>)’
thing<int> t1 {{{1,2},{3,4}}};
Run Code Online (Sandbox Code Playgroud)
同上
thing<int> t0{{ 1, 2, 3, 4 }};
Run Code Online (Sandbox Code Playgroud)
和其他几件事.
使用clang 3.5.0和gcc 4.9.1编译以下代码会在最后一个语句中产生错误.
#include <iostream>
struct Foo { Foo(int x, int y) { std::cout << "Foo(int = " << x << ", int = " << y << ")" << std::endl; } };
void bar(int x, int y) { std::cout << "bar(int = " << x << ", int = " << y << ")" << std::endl; }
int main()
{
Foo({}, {}); // Foo(int = 0, int = 0)
Foo({1}, {2}); // Foo(int = 1, int = 2)
Foo({1, …Run Code Online (Sandbox Code Playgroud) 我想我错过了什么,我不知道到底是什么.我们来看看代码片段.
template <typename T>
struct Foo {
Foo (int n, int p, string s, T t = {})
: m_n {n}, m_p {p}, m_s {s}, m_t {t}
{}
const int m_n;
const int m_p;
const string m_s;
T m_t;
};
Run Code Online (Sandbox Code Playgroud)
用法如下:
Foo<int> f_int1 {1, 2, "A", 155};
Foo<int> f_int2 {1, 2, "A"};
Run Code Online (Sandbox Code Playgroud)
一切都像预期的那样.但是当我想将用户定义的类型作为Foo的T参数时,会发生一些错误.考虑:
struct Boo {
int z;
int l;
};
Run Code Online (Sandbox Code Playgroud)
用法:
Foo<Boo> f_boo1 {1, 2, "A"};
Foo<Boo> f_boo2 {1, 2, "A", {1, 2}};
Run Code Online (Sandbox Code Playgroud)
这两条指令都给出了(gcc 4.8.1):
cannot convert ‘Boo’ to …Run Code Online (Sandbox Code Playgroud) 给定以下结构:
struct ABC
{
ABC(){cout << "ABC" << endl;}
~ABC() noexcept {cout << "~ABC" << endl;}
ABC(ABC const&) {cout << "copy" << endl;}
ABC(ABC&&) noexcept {cout << "move" << endl;}
ABC& operator=(ABC const&){cout << "copy=" << endl;}
ABC& operator=(ABC&&) noexcept {cout << "move=" << endl;}
};
Run Code Online (Sandbox Code Playgroud)
输出:
std::pair<std::string, ABC> myPair{{}, {}};
Run Code Online (Sandbox Code Playgroud)
是:
ABC
copy
~ABC
~ABC
Run Code Online (Sandbox Code Playgroud)
而输出:
std::pair<std::string, ABC> myPair{{}, ABC{}};
Run Code Online (Sandbox Code Playgroud)
是:
ABC
move
~ABC
~ABC
Run Code Online (Sandbox Code Playgroud)
在试图理解两者之间的差异时,我认为我已经确定第一种情况是使用复制列表初始化,而第二种情况使用未命名临时的直接列表初始化(数字7和2分别在这里) :http://en.cppreference.com/w/cpp/language/list_initialization).
搜索类似的问题我发现:为什么标准区分直接列表初始化和复制列表初始化?并且:复制列表初始化是否从概念上调用了复制ctor?.
这些问题的答案讨论了这样一个事实:对于复制列表初始化,使用显式构造函数会使代码格式错误.事实上,如果我将ABC的默认构造函数显式化,我的第一个例子将不会编译,但这可能是(可能)另一个问题.
所以,问题是:为什么临时复制在第一种情况下,但在第二种情况下移动?什么阻止它在复制列表初始化的情况下被移动?
作为注释,以下代码: …
所以我知道代码中的大括号不仅仅意味着initializer_list:如果不是intializer_list,那么什么是Curly-Brace封闭列表?
但他们应该默认什么?
例如,假设我定义了一个重载函数:
void foo(const initializer_list<int>& row_vector) { cout << size(row_vector) << "x1 - FIRST\n"; }
void foo(const initializer_list<initializer_list<int>>& matrix) { cout << size(matrix) << 'x' << size(*begin(matrix)) << " - SECOND\n"; }
Run Code Online (Sandbox Code Playgroud)
如果我打电话foo({ 1, 2, 3 })给第一个显然会被调用.如果我打电话foo({ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } })给第二人显然会被召唤.
但如果我打电话怎么办:
foo({ { 1 }, { 2 }, { 3 } })
Run Code Online (Sandbox Code Playgroud)
那些嵌套的括号 …
我正在尝试实现具有以下特征的模板化C数组:
// template definition
template< int a, int b > constexpr int arr[] = { 1 };
// partial specialization, works ok
template< int b > constexpr double arr<0, b>[] = { 2.0 };
// full specialization, compile error in MSVC, ok in g++
template< > constexpr float arr<1, 0>[] = { 3.0f };
Run Code Online (Sandbox Code Playgroud)
我将Visual Studio 2017和MSVC编译器与C ++标准设置为C ++ 17一起使用,并且编译器抱怨了C2133: 'arr<1,0>': unknown size,因此将大小添加1到完整的专业化解决了该错误。但是,它会在带有-pedantic标志的Ubuntu g ++ 8.1.0下进行编译。
我认为,对函数和类的完全专业化的行为就好像定义了非模板版本一样,因此我想这也应适用于变量模板,并且上面的完全专业化可以等同于(名称除外)
constexpr float arr_with_a1_and_b0[] = { 3.0f }; …Run Code Online (Sandbox Code Playgroud) c++ language-lawyer list-initialization template-variables c++17
以下代码在Clang中编译良好,并输出int [3]数组的大小
#include <iostream>
int main()
{
const int (&a)[] = { 1, 2, 3 };
std::cout << sizeof a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是,在GCC中,该声明可以很好地编译,但sizeof a不能编译:显然,GCC拒绝“推导”数组大小,最终a以引用const int []类型的方式结束,这是不完整的。
这种初始化的预期行为是什么?
在这种情况下,9.3.4 / 3似乎是标准的相关部分,但就其本身而言,似乎并不能得出结论。
如何在没有任何警告或错误的情况下进行编译和运行?我不明白如何将current的int 取消引用值分配给字符串,a而不会出现任何问题。
class Test {
public:
string a;
Test(initializer_list<int> t) {
auto current = t.begin();
// I am assigning an int to a string!
a = *current;
}
};
int main() {
Test test{65};
printf("%s\n", test.a.c_str());
}
Run Code Online (Sandbox Code Playgroud)
打印的字符串是
A
Run Code Online (Sandbox Code Playgroud)
相反,此非常相似的代码会产生编译时错误:
int main() {
initializer_list<int> test1{65};
auto current = test1.begin();
string b = *current;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误是:
error: no viable conversion from 'const int' to 'std::__1::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
string b = *current;
Run Code Online (Sandbox Code Playgroud)