在C++中,你会看到void func(const T& t)
无处不在.但是,我在.NET中没有看到类似的东西.为什么?
我注意到使用struct的参数很多.但是我看不到readonly/const的函数.事实上,现在我尝试了它,我不能使用这些关键字来制作一个承诺不修改传入的列表的函数.有没有办法让调用者承诺这个函数永远不会修改列表的内容?有没有办法说调用代码并说这个列表永远不应该被修改?(我知道我可以克隆列表或查看文档,但我喜欢编译错误)
我创建了几个目前只有标头的 C++库.我的类的接口和实现都写在同一个.hpp
文件中.
我最近开始认为这种设计不是很好:
我真的很喜欢只有头文件库的方面:所有函数都可以内联,并且它们非常容易包含在你的项目中 - 不需要编译/链接任何东西,只需要一个简单的#include
指令.
是否有可能充分利用两个世界?我的意思是 - 允许用户选择他/她想要如何使用库.它还可以加快开发速度,因为我以"动态链接模式"处理库以避免荒谬的编译时间,并以"仅标题模式"发布我的成品以最大化性能.
第一个逻辑步骤是将接口和实现划分为.hpp
和.inl
文件.
不过,我不确定如何前进.我已经看到很多库将LIBRARY_API
宏添加到它们的函数/类声明中 - 可能需要类似的东西来允许用户选择?
我的所有库函数都以inline
关键字为前缀,以避免"多个定义......"错误.我假设关键字将被文件中的LIBRARY_INLINE
宏替换.inl
?宏将解析inline
为"仅标题模式",而不是"动态链接模式".
我最近遇到了使用fstream :: eof()引起的问题.我从这里读到以下内容:
如果已到达关联输入文件的末尾,则函数eof()将返回true,否则返回false.
并且(错误地)假设这意味着如果我使用fstream :: read()并读取文件末尾,函数eof()会告诉我.所以我做了这样的事情(非常概括):
for(int i = 0; i < max && !file.eof(); i++)
{
file.read(mything, sizeof(mything));
}
Run Code Online (Sandbox Code Playgroud)
出现这个问题的原因是上面链接的页面稍后解释了(由于误导性的第一段,我最初没有阅读):
相反,如果在最后一个令牌之后恰好有任何空格,则流不会进入EOF状态,但尝试读取另一个令牌仍然会失败.因此,EOF标志不能用作用于在EOF之前读取所有流内容的循环中的测试.相反,应该在尝试阅读后检查失败条件.
所以我改变了,现在我的循环检查file.fail()而不是file.eof(),我理解如何工作eof().我的问题是,为什么这样做?有没有这种情况需要?在我看来,一旦你通过EOF,你已经通过了EOF而eof()应该返回true.
更新 感谢您的回复,我想我已经得到了.我正在执行的唯一操作是read(),我立即检查fail(),所以我觉得我没事.现在,我的问题是,我将使用eof()?
今天,我们发现,对于乘除,仿函数被称为std::multiplies
和std::divides
,而不是,例如, std::multiply
和std::divide
分别.
至少可以说这是令人惊讶的,考虑到std::plus
并且std::minus
没有以相同的方式制定.
差异有特殊原因吗?
在准备一个库(让我们称之为libfoo)时,我发现自己面临以下困境:我是否将其编写为带有C包装器的C++库:
namespace Foo {
class Bar {
...
};
}
/* Separate C header. #ifdef __cplusplus omitted for brevity. */
extern "C" {
typedef void *FooBar;
FooBar* foo_bar_new() { return new Foo::Bar; }
void foo_bar_delete(FooBar *bar) { delete bar; }
}
Run Code Online (Sandbox Code Playgroud)
或者将它编写为带有C++包装器的C库更好:
/* foo/bar.h. Again, #ifdef __cplusplus stuff omitted. */
typedef struct {
/* ... */
} FooBar;
void foo_bar_init(FooBar *self) { /* ... */ }
void foo_bar_deinit(FooBar *self) { /* ... */ }
/* foo/bar.hpp */
namespace Foo { …
Run Code Online (Sandbox Code Playgroud) 标准C++中有算法std::count
/ std::count_if
.
template<class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const T& value);
template<class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type
count_if(InputIterator first, InputIterator last, Predicate pred);
Run Code Online (Sandbox Code Playgroud)
效果:返回以下相应条件所适用的[first,last]范围内的迭代器数量:*i == value,pred(*i)!= false.
difference_type
是iterator's difference_type
,可以是负数,但count
只能返回值> = 0.为什么difference_type
而不是size_t
例如?
IList<T>
不继承IList
那里IEnumerable<out T>
继承IEnumerable
.
如果out
修正是唯一的原因,那么为什么大多数的实施IList<T>
(例如Collection<T>
,List<T>
)实现IList
接口.
所以任何人都可以说好,如果那些陈述对于所有的实现都是真的,IList<T>
那么IList
在必要时直接将其强制转换.但问题是虽然IList<T>
没有继承IList
所以不能保证每个IList<T>
对象都是IList
.
此外,使用IList<object>
显然不是解决方案,因为没有out
修饰符泛型不能分配给较少的继承类; 并且创建List的新实例在这里不是解决方案,因为有人可能想要实际引用IList<T>
作为IList
指针; 并且使用List<T>
insteed IList<T>
实际上是一种糟糕的编程习惯,并不能用于所有目的.
如果.NET希望提供灵活性,每个实现IList<T>
都不应该有非泛型实现的合同(即IList
)那么为什么他们没有保留另一个实现泛型和非泛型版本的接口,并没有暗示所有具体的想要签订通用和非遗传项目的类应通过该接口签订合同.
发生铸造同样的问题ICollection<T>
,以ICollection
及IDictionary<TKey, TValue>
对IDictionary
.
我知道在TLI控件(如TListBox)上使用BeginUpdate和EndUpdate会加快使用Items填充控件的过程,因为它会阻止控件重新绘制,直到调用EndUpdate.
例:
procedure TForm1.AddItems;
var
i: Integer;
begin
Screen.Cursor := crHourGlass;
try
for i := 0 to 5000 do
begin
ListBox1.Items.Add('Item' + IntToStr(i));
end;
finally
Screen.Cursor := crDefault;
end;
end;
Run Code Online (Sandbox Code Playgroud)
上面会有延迟,因为允许重新绘制列表框,但是可以通过防止重新绘制来缩短延迟:
procedure TForm1.AddItems;
var
i: Integer;
begin
Screen.Cursor := crHourGlass;
try
ListBox1.Items.BeginUpdate;
try
for i := 0 to 5000 do
begin
ListBox1.Items.Add('Item' + IntToStr(i));
end;
finally
ListBox1.Items.EndUpdate;
end;
finally
Screen.Cursor := crDefault;
end;
end;
Run Code Online (Sandbox Code Playgroud)
现在我使用TStringList测试了这个:
procedure TForm1.AddItems;
var
SL: TStringList;
i: Integer;
begin
SL := TStringList.Create;
try
Screen.Cursor := crHourGlass; …
Run Code Online (Sandbox Code Playgroud) library-design ×10
c++ ×5
.net ×3
c++11 ×2
c ×1
c# ×1
const ×1
delphi ×1
function ×1
generics ×1
header-only ×1
iostream ×1
libraries ×1
parameters ×1
scala ×1