当const对象被销毁时,有没有办法从析构函数中调用const成员函数?
考虑:
struct My_type {
~My_type () {
show ();
}
void show () {
cout << "void show ()" << endl;
}
void show () const {
cout << "void show () const" << endl;
}
};
Run Code Online (Sandbox Code Playgroud)
用法:
My_type mt;
const My_type cmt;
mt.show ();
cmt.show ();
Run Code Online (Sandbox Code Playgroud)
输出:
void show ()
void show () const
void show ()
void show ()
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下为什么cmt被销毁时没有调用const版本的show ?
我在理解在成员对象初始化期间抛出异常(来自构造函数)时发生的事情时,我已经失去了信心(可能还有2个小时).
让我告诉你一个例子:
int init (int f) {
throw f;
}
struct X {
X (int f) : n {init (f)} {}
int n;
};
struct P {
X x {20};
};
Run Code Online (Sandbox Code Playgroud)
和用法:
int main (int argc, char** argv) {
try {
P p {};
}
catch (int n) {
std::cout << n << "\n";
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码(C++ 11模式)编译得很好(使用GCC 7.2.1),在Linux(Centos 7.4.1708)下我得到:
terminate called after throwing an instance of 'int'
[1] 1242 abort (core dumped) ./main
Run Code Online (Sandbox Code Playgroud)
问题是:为什么?
为什么catch()不采取部分?
我已经跟踪了这个问题,这意味着当我的 …
请考虑以下代码:
void foo (M&) {}
M m;
foo ({m});
Run Code Online (Sandbox Code Playgroud)
因此,表达式{m}被视为rvalue引用,这就是此代码无法编译的原因.
这是真的{object}总是产生临时对象吗?
如果没有,那么如何确定它何时发生?如果是,请考虑以下代码:
struct M {};
struct I {
I (M&) {}
};
struct MM {
MM (M& p)
: m (p), i ( {p} )
{}
M& m;
I i;
};
M m;
MM mm {m};
Run Code Online (Sandbox Code Playgroud)
这里完全没有问题,那么{m}从第一个例子和{p}第二个例子之间的区别是什么?
编译器(GCC 4.8.1)结果(第一个例子):
main.cpp:366:13: error: invalid initialization of non-const reference of type ‘M&’ from an rvalue of type ‘<brace-enclosed initializer list>’
foo ({m});
^
main.cpp:359:6: error: …Run Code Online (Sandbox Code Playgroud) 考虑以下两个例子:
struct A {
A () noexcept = default;
};
struct B : A {
B () noexcept = default;
template <typename T>
B (T) noexcept {}
};
struct C : A {
using A::A;
template <typename T>
C (T) noexcept {}
};
Run Code Online (Sandbox Code Playgroud)
和用法:
std::cout << std::is_nothrow_constructible<B>::value << std::endl; // (X)
std::cout << std::is_nothrow_constructible<B, int>::value << std::endl;
std::cout << std::is_nothrow_constructible<C>::value << std::endl; // (Y)
std::cout << std::is_nothrow_constructible<C, int>::value << std::endl;
Run Code Online (Sandbox Code Playgroud)
输出是:
1
1
0
1
Run Code Online (Sandbox Code Playgroud)
使用的编译器:GCC 4.8.1.
所以,如果我显式写默认B构造函数, …
请考虑以下代码:
static constexpr size_t Num {2};
struct S {
std::array<size_t, Num> get () { return {1, 2}; }
};
struct S1 : S {};
struct S2 : S {};
struct M {
template <typename T>
typename std::enable_if<std::is_same<T, S1>::value, S1>::type get () const {
return S1 {};
}
template <typename T>
typename std::enable_if<std::is_same<T, S2>::value, S2>::type get () const {
return S2 {};
}
};
Run Code Online (Sandbox Code Playgroud)
我想要一个合并两个或多个std::arrays 的功能std::array.
到目前为止,我结束了这样的事情:
template <typename Mode, typename... Rs, size_t... Ns>
std::array<size_t, sizeof... (Rs)*Num> …Run Code Online (Sandbox Code Playgroud) 我们先来看看具体的功能:
void boo1 () { std::cout << "boo1\n"; }
void boo2 (std::string) { std::cout << "boo2\n"; }
struct X {
void boo3 () { std::cout << "boo3\n"; }
void boo4 (std::string) { std::cout << "boo4\n"; }
};
Run Code Online (Sandbox Code Playgroud)
我希望这些函数可以通过一些"保护"功能来执行,它可以进行异常保护(下面的说明).所以,我写了两个函数,一个用于自由函数,另一个用于成员函数:
template <typename C, typename... Args>
typename std::enable_if<!std::is_member_function_pointer<C>::value, void>::type
foo (C&& c, Args&&... args) {
std::cout << "not memfun\n";
c (std::forward<Args> (args)...);
}
template <typename C, typename T, typename... Args>
typename std::enable_if<std::is_member_function_pointer<C>::value, void>::type
foo (C&& c, T* o, Args&&... args) {
std::cout << …Run Code Online (Sandbox Code Playgroud) 从C++ 17开始我就能做到
std::pair<int, double> init () {
return std::make_pair (1, 1.2);
}
void foo () {
const auto [x, y] = init ();
std::cout << x << " " << y << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这很酷,但有什么办法可以一次初始化多个成员吗?我的意思是:
struct X {
X () : [x, y] {read_from_file_all_values ()} {}
std::pair<int, double> read_from_file_all_values () {
// open file, read all values, return all
return std::make_pair (1, 1.2);
}
const int x;
const double y;
};
Run Code Online (Sandbox Code Playgroud)
我知道,由于语法原因,这不起作用.我也知道我可以将所有值存储在相应的std::pair成员里面X,并使getter过载丑陋的std::get<N> ()语法,但是有什么办法可以用单个init() …
我想我错过了什么,我不知道到底是什么.我们来看看代码片段.
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) 请考虑以下代码段:
template <typename U>
struct Un {
Un (int p) : n {p} {}
U operator+ (U v) const {
return U {n + v.n};
}
int n {};
};
struct R : Un<R> {
using Un::Un;
};
struct D : Un<D> {
using Un::Un;
D (R v) : Un {v.n} {}
operator R () const {
return n;
}
};
Run Code Online (Sandbox Code Playgroud)
用法如下:
template <typename T>
void what_type (T t) {
std::cout << "type R = " << std::is_same<T, R>::value << …Run Code Online (Sandbox Code Playgroud) 我对此不太确定,所以请解释一下它是如何工作的。
让我们考虑以下代码。
std::vector<std::string> vec {};
void add (std::vector<std::string>&& v) {
using iter = std::vector<std::string>::iterator;
vec.insert (vec.end (),
std::move_iterator<iter> (v.begin ()),
std::move_iterator<iter> (v.end ()));
}
Run Code Online (Sandbox Code Playgroud)
所有元素都会v被移动吗?std::vector<T>::insert()对于范围版本需要第一个和最后一个迭代器,因此有了这样的代码,它如何知道v.begin()+1 也必须移动?的实现是否std::vector<T>::insert()区分“正常”和“移动”迭代器?