我尝试用VS2013编译一些C++代码,unique_ptr::reset()
似乎没有用make_unique()
; 一个小的可编辑的repro代码片段如下:
#include <memory>
using namespace std;
int main() {
unique_ptr<int[]> p = make_unique<int[]>(3);
p.reset(make_unique<int[]>(10));
}
Run Code Online (Sandbox Code Playgroud)
从命令行编译:
Run Code Online (Sandbox Code Playgroud)C:\Temp\CppTests>cl /EHsc /W4 /nologo test.cpp
这些是来自MSVC编译器的错误:
Run Code Online (Sandbox Code Playgroud)test.cpp(6) : error C2280: 'void std::unique_ptr<int [],std::default_delete<_Ty> >::reset<std::unique_ptr<_Ty,std::default_delete<_Ty>>>(_Ptr2)' : attempting to reference a deleted function with [ _Ty=int [] , _Ptr2=std::unique_ptr<int [],std::default_delete<int []>> ] C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\memory(16 23) : see declaration of 'std::unique_ptr<int [],std::default_delete<_Ty>>::rese t' with [ _Ty=int [] ]
但是,以下代码似乎编译良好:
p = make_unique<int[]>(10);
Run Code Online (Sandbox Code Playgroud)
这种行为的原因是什么?为什么要unique_ptr::operator=()
合作make_unique()
,但unique_ptr::reset() …
我正在测试一些代码,其中std::vector
一个类中有一个数据成员.类是既可以复印和活动,并operator=
描述实现这里使用复制和交换成语.
如果有两个vector
s,比如v1
大容量和v2
小容量,并被v2
复制到v1
(v1 = v2
),则v1
在分配后保留大容量 ; 这是有道理的,因为下一次v1.push_back()
调用不必强制新的重新分配(换句话说:释放已经可用的内存,然后重新分配它来增长向量没有多大意义).
但是,如果对具有as数据成员的类进行相同的赋值vector
,则行为不同,并且在赋值之后不保留更大的容量.
如果不使用复制operator=
和交换习惯用法,并且复制和移动operator=
是分开实现的,那么行为就像预期的那样(对于普通的非成员vector
s).
这是为什么?我们是否应该遵循复制和交换习惯用法,而是分别实施operator=(const X& other)
(复制 op=
)和operator=(X&& other)
(移动 op=
)以获得最佳性能?
这是一个可重复的测试输出与复制和交换成语(注意如何在这种情况下,之后 x1 = x2
,x1.GetV().capacity()
就是1000,不1,000,000):
Run Code Online (Sandbox Code Playgroud)C:\TEMP\CppTests>cl /EHsc …
在" 如何设计我的异常类? "一节中的" 错误和异常处理 " Boost网页中,它显示为:
[...] 3. 不要嵌入std :: string对象或其复制构造函数可能引发异常的任何其他数据成员或基类.
我必须定义一个异常类来表示文件访问的某种形式的运行时错误,所以我想从中派生它std::runtime_error
,并添加一个FileName()
属性来访问发生错误的文件名.
为了简单起见,我的目的是添加一个std::wstring
数据成员来存储文件名(以Unicode格式),但上述建议让我感到不安.那么,我应该使用简单的wchar_t
缓冲区作为数据成员吗?
在现代桌面系统(这是我项目的目标平台)上,注意文件名的动态字符串分配是否真的很重要?这种分配失败的可能性有多大?我可以理解Boost对嵌入式系统等有限资源系统的建议,但它对现代台式机也有效吗?
//
// Original design, using std::wstring.
//
class FileIOError : public std::runtime_error
{
public:
FileIOError(HRESULT errorCode, const std::wstring& filename, const char* message)
: std::runtime_error(message),
m_errorCode(errorCode),
m_filename(filename)
{
}
HRESULT ErrorCode() const
{
return m_errorCode;
}
const std::wstring& FileName() const
{
return m_filename;
}
private:
HRESULT m_errorCode;
std::wstring m_filename;
};
//
// …
Run Code Online (Sandbox Code Playgroud) 是否std::unique_ptr
使C++ 11/14中的Boost.Pointer容器库过时了?
在C++ 98/03中,没有移动语义,并且如果与原始指针相比,智能指针shared_ptr
具有与引用计数相关的开销(对于ref计数块和互锁的递增/递减).因此,std::vector<shared_ptr<T>>
如果与之相比,就会产生开销std::vector<T*>
.
但std::vector<std::unqiue_ptr<T>>
正如高效的std::vector<T*>
(没有引用计数的开销),并且除了安全关于异常和自动破坏(即vector<unique_ptr<T>>
析构函数会自动调用析构函数对于T
其指针存储中的项目vector
)?
如果是这样,Boost.Pointer容器在C++ 11/14代码中仍然有一个有用的有用位置,还是刚刚过时?
在C++中,当输入参数是便宜的复制(例如像一个int
,float
等等),它通常是简单地通过由值.相反,输入复制(例如std::string
)不便宜的"观察"参数const &
.
我想知道像POD这样的类型代表具有int
坐标的2D矢量,例如
struct Vec2i
{
int X;
int Y;
};
Run Code Online (Sandbox Code Playgroud)
在32位MSVC编译器上,它只有8个字节(2 * sizeof(int)
).你会通过价值还是通过const &
?
那个Vec2d
有double
型坐标怎么样?
(在MSVC上,它将是2 * sizeof(double)
,所以2 * 8 = 16
字节.)
是否存在"大小阈值"(例如16个字节?)用于放置一条线并说:"对于大小为X的const &
POD经过,对于较小的POD经过值"?
PS:请不要在回复中使用参数作为"过早优化".
这对我来说听起来像的情况下,++it
对it++
(其中it
是一个STL迭代器):这并不是说++it
是一个不成熟的优化,问题是,it++
是过早pessimization :)
我试图读取纯文本文件.在我的情况下,我需要读取每行的行,并处理该信息.我知道C++有阅读wchars的功能.我尝试了以下方法:
#include <fstream>
#include <iostream>
int main() {
std::wfstream file("file"); // aaaàaaa
std::wstring str;
std::getline(file, str);
std::wcout << str << std::endl; // aaa
}
Run Code Online (Sandbox Code Playgroud)
但正如你所看到的,它没有读完整行.读取"à"时会停止,这是非ASCII.我该如何解决?
我正在将一些Unix代码移植到Windows Visual Studio 2010中.我遇到了以下问题
gmtime_r(&now, &tm_time);
Run Code Online (Sandbox Code Playgroud)
我发现gmtime_r()是一个标准的Unix函数,但我希望找到与Windows等价的函数.我在time.h中发现了很多gmtime函数,但是我很难找到哪一个是等价的,如果它存在的话.有人能指出我正确的方向吗?
在C++ 11中实现移动语义时,移动对象应该保持安全状态,还是只能处于"垃圾"状态?
例如,在以下C++ 11包装器示例中将原始FILE*
资源实现移动构造函数的首选选项是什么?
// C++11 wrapper to raw FILE*
class File
{
FILE* m_fp;
public:
// Option #1
File(File&& other)
: m_fp(other.m_fp)
{
// "other" left in a "junk" state
}
// Option #2
File(File&& other)
: m_fp(other.m_fp)
{
// Avoid dangling reference in "other"
other.m_fp = nullptr;
}
...
};
Run Code Online (Sandbox Code Playgroud) 我写了一个C++ DLL,现在我需要从托管应用程序调用本机函数.
导出的本机函数如下所示:
extern "C" __declspec(dllexport)
bool NativeMethod(char *param1, char *param2, char *result);
Run Code Online (Sandbox Code Playgroud)
所以,从C#我将调用该函数传递2个输入参数,1个输出参数,显然我将读取返回bool值.
我试图以多种方式包装所有这些,但总是我得到一个PInvokeStackImbalance
例外.我知道调用本机函数的唯一方法是通过应用CallingConvention = CallingConvention.Cdecl
).NET函数声明.但是通过这种方式,我无法读取输出参数(它总是空字符串),并且返回值始终为true.
我试图将32位dll(和应用程序)移植到64位,我已经设法构建它没有错误.当我尝试使用我的64位应用程序加载它时,我注意到导出的函数名称不同.这是我导出函数的方式:
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) long __stdcall Connect(char * name, long size);
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)
在Dependency Walker中,导出的函数具有以下格式:
32位: _Connect@8
64位: Connect
在使用dll的应用程序中,我显式加载了dll(LoadLibrary成功)但GetProcAddress因64位而失败,因为它找不到具有提供名称的函数.
在我们的应用程序中,我保留函数名称如下:
#define ConnectName "_Connect@8"
...
GetProcAddress(Dll, ConnectName);
Run Code Online (Sandbox Code Playgroud)
所以我想知道是否可以为32位和64位dll导出相同的函数名称,或者这是一个坏主意?或者我需要在我的应用程序中执行以下操作:
#if _WIN64
#define ConnectName "Connect"
#else
#define ConnectName "_Connect@8"
#endif
Run Code Online (Sandbox Code Playgroud)
我感谢任何帮助.