小编Mr.*_*C64的帖子

为什么make_unique不能与unique_ptr :: reset一起使用?

我尝试用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)

从命令行编译:

C:\Temp\CppTests>cl /EHsc /W4 /nologo test.cpp
Run Code Online (Sandbox Code Playgroud)

这些是来自MSVC编译器的错误:

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 []
        ]
Run Code Online (Sandbox Code Playgroud)

但是,以下代码似乎编译良好:

p = make_unique<int[]>(10);
Run Code Online (Sandbox Code Playgroud)

这种行为的原因是什么?为什么要unique_ptr::operator=()合作make_unique(),但unique_ptr::reset() …

c++ unique-ptr c++11 c++14

11
推荐指数
2
解决办法
5524
查看次数

复制和交换习语的效率低下?

我正在测试一些代码,其中std::vector一个类中有一个数据成员.类是既可以复印活动,并operator=描述实现这里使用复制和交换成语.

如果有两个vectors,比如v1大容量和v2小容量,并被v2复制到v1(v1 = v2),v1在分配后保留大容量 ; 这是有道理的,因为下一次v1.push_back()调用不必强制新的重新分配(换句话说:释放已经可用的内存,然后重新分配它来增长向量没有多大意义).

但是,如果对具有as数据成员的进行相同的赋值vector,则行为不同,并且在赋值之后保留更大的容量.

如果使用复制operator=和交换习惯用法,并且复制和移动operator=分开实现的,那么行为就像预期的那样(对于普通的非成员vectors).

这是为什么?我们是否应该遵循复制和交换习惯用法,而是分别实施operator=(const X& other)(复制 op=)和operator=(X&& other)(移动 op=)以获得最佳性能?

这是一个可重复的测试输出与复制和交换成语(注意如何在这种情况下,之后 x1 = x2,x1.GetV().capacity()就是1000,不1,000,000):

C:\TEMP\CppTests>cl /EHsc …
Run Code Online (Sandbox Code Playgroud)

c++ performance vector copy-and-swap c++11

10
推荐指数
2
解决办法
1290
查看次数

在现代PC上避免使用C++异常类中的std :: wstring数据成员是否有意义?

在" 如何设计我的异常类? "一节中的" 错误和异常处理 " 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)

c++ string boost memory-management exception

9
推荐指数
1
解决办法
1094
查看次数

Boost.Pointer容器在C++ 11/14中被std :: unique_ptr淘汰了?

是否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++ boost stl smart-pointers c++11

9
推荐指数
2
解决办法
1758
查看次数

输入参数传递:是否存在有效传值的大小阈值?

在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 &

那个Vec2ddouble型坐标怎么样?
(在MSVC上,它将是2 * sizeof(double),所以2 * 8 = 16字节.)

是否存在"大小阈值"(例如16个字节?)用于放置一条线并说:"对于大小为X的const &POD经过,对于较小的POD经过值"


PS:请不要在回复中使用参数作为"过早优化".
这对我来说听起来像的情况下,++itit++(其中it是一个STL迭代器):这并不是说++it是一个不成熟的优化,问题是,it++过早pessimization :)

c++ parameter-passing pass-by-value

9
推荐指数
1
解决办法
156
查看次数

如何在Linux上用std :: ifstream读取文件中的非ASCII行?

我试图读取纯文本文件.在我的情况下,我需要读取每行的行,并处理该信息.我知道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.我该如何解决?

c++ linux

9
推荐指数
1
解决办法
2710
查看次数

什么是Unix函数gmtime_r的Windows等价物?

我正在将一些Unix代码移植到Windows Visual Studio 2010中.我遇到了以下问题

gmtime_r(&now, &tm_time);
Run Code Online (Sandbox Code Playgroud)

我发现gmtime_r()是一个标准的Unix函数,但我希望找到与Windows等价的函数.我在time.h中发现了很多gmtime函数,但是我很难找到哪一个是等价的,如果它存在的话.有人能指出我正确的方向吗?

c++ unix time porting visual-studio-2010

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

移动物体是否应保持"安全"状态?

可能重复:
如何使用移动的对象?
什么构成C++ 11中"移动"对象的有效状态?

在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++ move-semantics c++11

8
推荐指数
2
解决办法
230
查看次数

为C#包装本机DLL

我写了一个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.

c# c++ string pinvoke

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

x64 DLL导出函数名称

我试图将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)

我感谢任何帮助.

c++ dll 64-bit name-mangling

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