在C和C++中,可以使用大括号初始化数组和结构:
int a[] = {2, 3, 5, 7};
entry e = {"answer", 42};
Run Code Online (Sandbox Code Playgroud)
然而,在2007年的一次演讲中,Bjarne提到这种语法也适用于标量.我尝试过这个:
int i = {7};
Run Code Online (Sandbox Code Playgroud)
它确实有效!允许使用大括号初始化标量的原理是什么?
注意:我特别不是在谈论C++ 11统一初始化.这是很好的旧C89和C++ 98.
初始化对抽象类型的引用时,构造函数初始化列表中的{}初始化如何与()初始化不同?以下课程栏:
class AbstractBase
{
public:
AbstractBase() {}
virtual ~AbstractBase() = default;
virtual void ab() = 0;
};
class Foo : public AbstractBase
{
public:
Foo() {}
void ab() {}
};
class Bar
{
public:
Bar(const AbstractBase& base) : myBase{base} {}
private:
const AbstractBase& myBase;
};
int main()
{
Foo f{};
Bar b{f};
}
Run Code Online (Sandbox Code Playgroud)
编译时,我收到错误
test5.cpp: In constructor ‘Bar::Bar(const AbstractBase&)’:
test5.cpp:22:48: error: cannot allocate an object of abstract type ‘AbstractBase’
Bar(const AbstractBase& base) : myBase{base}
^
test5.cpp:2:7: note: because the following …
Run Code Online (Sandbox Code Playgroud) 是new int[8]()
等同于new int[8]{}
在C++ 11?
换一种说法:
C++ 11标准是否保证每个new int[8]()
并new int[8]{}
返回零初始化数组?
我想创建一个const对象的临时副本,并以非const方式使用它:
struct S {
S& f() { return *this; }
};
int main() {
const S a{};
S{a}.f(); // Error on this line
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用msvc(Visual Studio 2017,C++ 14),我收到此错误:
错误C2662'S&S :: f(void)':无法将'this'指针从'const S'转换为'S&'
如果我将大括号初始化更改为经典初始化,它可以工作:
S{a}.f(); // Does not work
S(a).f(); // Works
Run Code Online (Sandbox Code Playgroud)
两种变体在gcc中编译都很好.我错过了什么或这是一个编译器错误?
此代码编译:
std::string f(bool a, std::string const& b)
{
if (a) return b;
return {};
}
Run Code Online (Sandbox Code Playgroud)
该代码还可以编译:
std::string f(bool a, std::string const& b)
{
return a ? b : std::string{};
}
Run Code Online (Sandbox Code Playgroud)
此代码无法编译:
std::string f(bool a, std::string const& b)
{
return a ? b : {};
}
Run Code Online (Sandbox Code Playgroud)
假设?:
运算符的两个结果值必须是同一类型,为什么它不像第一个示例中那样推断类型?
看来,这个问题可能有类似的答案,这(基本上可以归结为“因为没有人想过写的语言规范时”)。但是,我仍然认为保留该问题很有用,因为问题本身是不同的,这仍然足够令人惊讶,并且其他人不会在搜索此问题时出现。
c++ conditional-operator language-lawyer c++11 list-initialization
以下内容无法编译clang35 -std=c++11
:
#include <iostream>
#include <string>
#include <initializer_list>
class A
{
public:
A(int, bool) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(int, double) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(std::initializer_list<int>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main()
{
A a1 = {1, 1.0};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有错误
init.cpp:15:14: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
A a1 = {1, 1.0};
^~~
init.cpp:15:14: note: insert an explicit cast to silence …
Run Code Online (Sandbox Code Playgroud) 在[dcl.init] /17.6中,明确写出,对于括号初始化的情况,会发生复制省略:
如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象.[ 例子: T x = T(T(T())); 调用T默认构造函数来初始化x.- 结束例子 ]
但是在列表初始化的情况下,上面的段落不适用,我没有发现任何类似的东西.见[dcl.init.list].
那么为什么在这种情况下有复制省略:T x{T(T())};
根据C++ 17标准.
我怎样才能做到平等:
#include <vector>
size_t bufferSize = 1024 * 1024;
std::vector<unsigned char> buffer(bufferSize, ' ');
Run Code Online (Sandbox Code Playgroud)
使用列表(花括号)初始化?
当我尝试执行以下操作时:
#include <vector>
size_t bufferSize = 1024 * 1024;
std::vector<unsigned char> buffer {bufferSize, ' '};
Run Code Online (Sandbox Code Playgroud)
它错误地解释bufferSize
为要存储在容器的第一个索引中的值(即调用错误的std::vector
构造函数),并且由于从unsigned int
(size_t
)到()的转换无效而无法编译unsigned char
.
鉴于这个例子:
int g_i = 10;
struct S {
operator int&(){ return g_i; }
};
int main() {
S s;
int& iref1 = s; // implicit conversion
int& iref2 = {s}; // clang++ error, g++ compiles fine:
// `s` is converted
// to a temporary int and binds with
// lvalue reference
int&& iref3 = {s}; // clang++ compiles, g++ error:
// cannot bind rvalue reference
// to lvalue
}
Run Code Online (Sandbox Code Playgroud)
错误如评论中所述.
使用gcc 8.2.1和clang 7.0.1,并且不同意本例中发生的情况.有人可以澄清一下吗?
否则,如果初始化程序列表具有 …
c++ ×10
c++11 ×6
c ×1
c++17 ×1
constructor ×1
copy-elision ×1
reference ×1
standards ×1
temporary ×1