假设我有一节课:
class C{
int x_;
int y_;
public:
C(int x, int y): x_(x), y_(y){}
};
Run Code Online (Sandbox Code Playgroud)
然后我想从一个字符串添加构造,它只是解析x
和y
.在阅读迈耶斯的书之前,我通常会在课堂上将它作为另一个构造函数C
.但是,它也可以使其成为非会员非朋友:
C CFromString(const std::string& s){
int x, y;
//...parse them somehow, throw exception if needed...
return C(x,y);
}
Run Code Online (Sandbox Code Playgroud)
对我来说,这是许多"值类"的标准情况,当有一个"主"构造函数将私有成员设置为提供的值(可能检查正确性).这些类的其他构造函数通常只是从其他一些参数计算这些值.
在我的例子中,使这样的构造函数成为非成员非朋友有什么缺点吗?
UPD.我理解Meyers的建议,以及NMNF功能的优点.在他的书中没有关于NMNF对象构造的例子,所以我想确保他的建议也适用于建筑.
是否存在可能导致 C++ 异常的“代码语句”的完整列表(可能是递归定义的)?像这样的东西:
1)throw
声明(自然)
2) 调用new
3) 调用标准库中记录为能够抛出异常的任何函数。
4) 调用包含 1-3 操作的任何用户定义函数(包括构造函数)。
5)还有别的事吗?在堆栈上分配本地对象、对内置类型的操作、取消引用指针、类型转换 - 它们能够抛出异常吗?
6) 其他一切均无异常。
我所说的无异常并不是指总是成功的操作。取消引用指针肯定不是。但将其包装在块中仍然没有意义try-catch
,考虑函数取消引用指针的异常安全性等。因此,成功或导致未定义行为的代码可以被视为无异常。
更新。尽管我写了最后一段,但我仍然得到了一条评论,即未定义的行为也可能抛出,所以让我解释一下我的意思。考虑以下代码:
void bar();
Class C{
...
public:
foo() {
something_that_breaks_class_invariants;
bar();
something_that_restores_class_invariants;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我正确理解异常安全是什么,那么如果bar()
可以抛出异常,那么这段代码就很糟糕。我应该改变语句的顺序,或者我应该包装bar()
在try-catch
块中,恢复类不变量并进一步传播异常。
但是,如果 bar() 成功返回或导致未定义的行为(因为,我不知道,其他东西被破坏了),那么就foo()
可以了。foo()
不能做任何事情,也不应该关心 可能的未定义行为bar()
。从这个意义上讲bar()
是无异常的,可以标记的noexcept
,等等。
所以我的问题是:什么样的语句可以认为bar()
它是无异常的?
"严格地"是指"没有相同的元素".
is_sorted(v.begin(), v.end(), std::less<>())
Run Code Online (Sandbox Code Playgroud)
不符合我的目标,因为它对于像这样的范围返回true 1,2,2,4,5
.
is_sorted(v.begin(), v.end(), std::less_equal<>())
Run Code Online (Sandbox Code Playgroud)
将根据这里给出的实现工作,但不幸的是is_sorted
要求Compare
谓词是严格的排序(Compare(a,a)
必须是假的),std::less_equal
当然不是.
那么我应该为此目的编写自己的循环吗?
这是我想要阻止的:
class Dep; //for "dependency"
class C {
private:
const Dep& dep_; //or std::shared_ptr if I want to guarantee proper lifetime of dependency
public:
C(const Dep& dep) : dep_(dep){}
}
Dep d(Arg arg);
C obj(d); //obj can't change d
d.some_non_const_method(); //But it's creator can :(
Run Code Online (Sandbox Code Playgroud)
我想得到的是,创建C
对象的唯一正确方法是这样的:
Dep d(Arg arg);
d.some_non_const_method();
const Dep d1(d); //or move constructor if appropriate
C obj(d1); //Object d1 must be const!
d1.some_non_const_method(); //compile error, so obj can be sure that the dependency he's got …
Run Code Online (Sandbox Code Playgroud) 我对std :: transfrom 的以下描述感到困惑:
unary_op - 将应用的一元操作函数对象.函数的签名应该等同于以下内容:
Ret fun(const Type &a);
签名不需要
const &
.
这两个陈述似乎是矛盾的.有人可以澄清这里的意思吗?如果签名是会发生什么Ret fun(Type a)
或Ret fun(Type&& a)
或Ret fun(Type& a)
?
如果在调用像input_stream >> i;
这里i
是算术型,抛出异常或设置badbit等,是保证i
并没有改变?