我目前正在尝试理解C++ 0x的新统一初始化.不幸的是,我对使用引用的统一初始化感到困惑.例:
int main() {
int a;
int &ref{a};
}
Run Code Online (Sandbox Code Playgroud)
这个例子工作正常:
% LANG=C g++ uniform_init_of_ref.cpp -std=c++0x -o uni -Wall -Wextra
uniform_init_of_ref.cpp: In function `int main()':
uniform_init_of_ref.cpp:3:10: warning: unused variable `ref' [-Wunused-variable]
Run Code Online (Sandbox Code Playgroud)
(更新 Comeau会为该示例抛出错误,因此gcc也不应该编译它)
现在,如果我使用自定义数据类型而不是整数,它将不再起作用:
class Y
{};
int main()
{
Y y;
Y &ref{y};
}
% LANG=C g++ initialization.cpp -std=c++0x -o initialization -Wall -Wextra
initialization.cpp: In function `int main()':
initialization.cpp:9:13: error: invalid initialization of non-const reference of type `Y&' from an rvalue of type `<brace-enclosed initializer list>'
initialization.cpp:9:8: warning: …Run Code Online (Sandbox Code Playgroud) 在统一初始化期间使用尾随逗号时是否存在任何潜在的语义差异?
std::vector< std::size_t > v1{5, }; // allowed syntax
std::vector< std::size_t > v2{10};
Run Code Online (Sandbox Code Playgroud)
我可以使用尾随逗号来使编译器选择std::vector::vector(std::initializer_list< std::size_t >)构造函数而不是std::vector::vector(std::size_t, const std::size_t &)或者是否有任何其他提及语法的技巧?
我可以使用它来检测是否有 - std::initializer_list构造函数重载?
考虑以下代码,必须选择哪个构造函数?
struct A { A(int) { ; } A(double, int = 3) { ; } };
A a{1};
A b{2, };
Run Code Online (Sandbox Code Playgroud)
此代码是由受理gcc 8并A(int)在两种情况下被选中.
像许多人一样,我对C++ 0x感到非常兴奋.我尝试在新项目中学习和使用新功能,这样我就可以编写最好,最易于维护的代码.
不用说,我喜欢新初始化器背后的想法.所以我在看他们,这些对我有意义:
T x = { 1, 2, 3 }; // like a struct or native array
T x({1, 2, 3}); // copy construct something like an "object literal" in other languages... cool!
return {1, 2, 3}; // similar to above, but returning it, even cooler!
Run Code Online (Sandbox Code Playgroud)
对我来说没有意义的是:
T x{1, 2, 3};
Run Code Online (Sandbox Code Playgroud)
它只是感觉......很奇怪.我不确定人们想要使用哪种语法,这是模仿,它似乎并不"正确".
这种语法背后的设计/思想是什么?
它似乎有所作为的唯一例子是这样的:
std::vector<int> the_vec{4};
Run Code Online (Sandbox Code Playgroud)
它会调用初始化列表构造函数,但为什么不写这个呢:
std::vector<int> the_vec = {4};
Run Code Online (Sandbox Code Playgroud)
并做每个人都已经习惯的事情?
我有以下课程:
struct foo
{
std::size_t _size;
int* data;
public:
explicit foo(std::size_t s) : _size(s) { }
foo(std::size_t s, int v)
: _size(s)
{
data = new int[_size];
std::fill(&data[0], &data[0] + _size, v);
}
foo(std::initializer_list<int> d)
: _size(d.size())
{
data = new int[_size];
std::copy(d.begin(), d.end(), &data[0]);
}
~foo() { delete[] data; }
std::size_t size() const { return _size; }
};
Run Code Online (Sandbox Code Playgroud)
我想像这样向它转发论据:
template <typename... Args>
auto forward_args(Args&&... args)
{
return foo{std::forward<Args>(args)...}.size();
//--------^---------------------------^
}
std::cout << forward_args(1, 2) << " " << forward_args(1) …Run Code Online (Sandbox Code Playgroud) 我无法理解何时以及如何在C++ 11中使用新的统一初始化语法.
例如,我得到这个:
std::string a{"hello world"}; // OK
std::string b{a}; // NOT OK
Run Code Online (Sandbox Code Playgroud)
为什么在第二种情况下不起作用?错误是:
error: no matching function for call to ‘std::basic_string<char>::basic_string(<brace enclosed initializer list>)’
Run Code Online (Sandbox Code Playgroud)
使用此版本的g ++ g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2.
对于原始数据,我应该使用什么语法?
int i = 5;
int i{5};
int i = {5};
Run Code Online (Sandbox Code Playgroud) C++ 11
程序初始化一个vector名为s的命名myVec,int vector然后使用一个循环打印出每个内部vector元素.但是当我试图看到当我使用额外的花括号时会发生什么,我得到了意想不到的结果.以下内容也适用于此LiveWorkSpace,以便在编译器之间轻松切换.g++ 4.8.0只汇编到myVec[5].clang++ 3.2汇编一切:
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>> myVec =
{
/* myVec[0] */ {1, 2},
/* myVec[1] */ {},
/* myVec[2] */ {{}},
/* myVec[3] */ { {}, {} },
/* myVec[4] */ { {}, {}, {} },
/* myVec[5] */ {{{}}}
/* myVec[6] */ // , { {{}}, {{}} } // g++ 4.8.0 COMPILER ERROR
/* …Run Code Online (Sandbox Code Playgroud) 统一初始化是一个重要且有用的C++ 11特性.但是,您不能{}随处使用,因为:
std::vector<int> a(10, 0); // 10 elements of value zero
std::vector<int> b({10, 0}); // 2 elements of value 10 and 0 respectively
std::vector<int> c{10, 0}; // 2 elements of value 10 and 0 respectively
std::vector<int> d = {10, 0}; // 2 elements of value 10 and 0 respectively
auto e(0); // deduced type is int
auto f = 0; // deduced type is int
auto g{0}; // deduced type is std::initializer_list<int>
auto h = {0}; // …Run Code Online (Sandbox Code Playgroud) 将下面的代码不会用gcc编译:
struct test {
int x;
test() try : x{123} {
}
catch (...) {
}
};
int main() {}
Run Code Online (Sandbox Code Playgroud)
错误:
prog.cpp:3:25: error: expected unqualified-id before ‘{’ token
test() try : x{123} {
^
prog.cpp:5:5: error: expected unqualified-id before ‘catch’
catch (...) {
^
prog.cpp: In constructor ‘test::test()’:
prog.cpp:3:23: error: expected ‘{’ at end of input
test() try : x{123} {
^
prog.cpp:3:23: error: expected ‘catch’ at end of input
prog.cpp:3:23: error: expected ‘(’ at end of input …Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
#include <vector>
#define BROKEN
class Var {
public:
#ifdef BROKEN
template <typename T>
Var(T x) : value(x) {}
#else
Var(int x) : value(x) {}
#endif
int value;
};
class Class {
public:
Class(std::vector<Var> arg) : v{arg} {}
std::vector<Var> v;
};
Run Code Online (Sandbox Code Playgroud)
不管是否BROKEN定义,Clang ++(7.0.1)都会编译此错误,而如果BROKEN已定义,则g ++(8.2.1)会引发错误:
main.cpp:9:20: error: cannot convert ‘std::vector<Var>’ to ‘int’ in initialization
Var(T x) : value(x) {}
^
Run Code Online (Sandbox Code Playgroud)
据我所知,std::vector(std::vector&&)在两种情况下,这里使用的统一初始化都应选择构造函数。但是,显然,g++它将{arg}视为初始化列表,并尝试初始化应用于向量的vwith 的第一个元素Var,这将不起作用。
如果BROKEN未定义,则g ++显然足够聪明,可以意识到initializer_list重载将无法正常工作。
哪个是正确的行为,或者标准都允许? …