相关疑难解决方法(0)

为什么列表初始化(使用花括号)比替代品更好?

MyClass a1 {a};     // clearer and less error-prone than the other three
MyClass a2 = {a};
MyClass a3 = a;
MyClass a4(a);
Run Code Online (Sandbox Code Playgroud)

为什么?

我在SO上找不到答案,所以让我回答一下我自己的问题.

c++ syntax initialization c++11 list-initialization

349
推荐指数
5
解决办法
13万
查看次数

何时使用支架封闭的初始化器?

在C++ 11中,我们有了用于初始化类的新语法,它为我们提供了如何初始化变量的大量可能性.

{ // Example 1
  int b(1);
  int a{1};
  int c = 1;
  int d = {1};
}
{ // Example 2
  std::complex<double> b(3,4);
  std::complex<double> a{3,4};
  std::complex<double> c = {3,4};
  auto d = std::complex<double>(3,4);
  auto e = std::complex<double>{3,4};
}
{ // Example 3
  std::string a(3,'x');
  std::string b{3,'x'}; // oops
}
{ // Example 4
  std::function<int(int,int)> a(std::plus<int>());
  std::function<int(int,int)> b{std::plus<int>()};
}
{ // Example 5
  std::unique_ptr<int> a(new int(5));
  std::unique_ptr<int> b{new int(5)};
}
{ // Example 6
  std::locale::global(std::locale("")); // copied from 22.4.8.3 …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list c++11

91
推荐指数
3
解决办法
3万
查看次数

{x}和'= {x}'初始化之间有什么区别?

我试图理解这两种初始化方式之间的语义差异:

Foo foo{x};
Foo foo = {x};
Run Code Online (Sandbox Code Playgroud)

我很想知道以下情况的区别:

  1. x是类型的Foo.
  2. Foo 有一个构造函数,它接受与x相同类型的参数.
  3. x不是类型,Foo但可以使用转换构造函数.
  4. x不是类型,Foo但可以使用explicit转换构造函数.

根据差异我的意思是,在每种情况下:

  1. 从概念上讲,调用哪些构造函数?
  2. 哪些构造函数调用通常由编译器优化?
  3. 是否允许隐式转换?

c++ c++11

17
推荐指数
1
解决办法
829
查看次数

RAII和推导出的模板参数

这是我经常遇到的RAII问题.我想知道是否有人有一个很好的解决方案.

从标准RAII实用程序类开始:

class RAIIHelper {
  RAIIHelper() {
    AcquireAResource();
  }
  ~RAIIHelper() {
    ReleaseTheResource();
  }
};
Run Code Online (Sandbox Code Playgroud)

现在,由于各种原因,我需要将其作为模板.我们还说它的构造函数接受模板参数类型的参数:

template <typename T>
class RAIIHelper {
  RAIIHelper(T arg) {
    AcquireAResource();
  }
  ~RAIIHelper() {
    ReleaseTheResource();
  }
};
Run Code Online (Sandbox Code Playgroud)

现在考虑使用网站:

void func() {
  RAIIHelper<SomeType> helper(someObj);
}
Run Code Online (Sandbox Code Playgroud)

SomeType当它可以从中推断时必须写出来很烦人someObj,因此我编写了一个辅助函数来推断出类型:

template <typename T>
RAIIHelper<T> makeRAIIHelper(T arg) {
  return RAIIHelper<T>(arg);
}
Run Code Online (Sandbox Code Playgroud)

现在我可以像这样使用它:

void func() {
  auto helper = makeRAIIHelper(someObj);
}
Run Code Online (Sandbox Code Playgroud)

很棒,对吧?除了有一个障碍:RAIIHelper现在需要是可复制的或可移动的,并且释放资源的析构函数可能被调用两次:一次用于返回的临时值makeRAIIHelper,一次用于调用函数中的局部变量.

实际上,我的编译器执行RVO,并且只调用析构函数一次.但是,这不能保证.这可以从以下事实看出:如果我尝试给出RAIIHelper一个= delete'd move构造函数,代码就不再编译了.

我可以向RAIIHelper添加额外的状态,以便它知道ReleaseTheResource()在移动之后不会调用,但这是额外的工作,在我添加makeRAIIHelper()以获得类型扣除之前是不必要的.

有没有办法可以获得类型演绎,而无需添加额外的状态RAIIHelper …

c++ templates raii c++11

8
推荐指数
1
解决办法
361
查看次数